[PR #793] [MERGED] fix(app-router): pass searchParams to layout generateMetadata #852

Closed
opened 2026-05-06 13:10:28 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/793
Author: @NathanDrake2406
Created: 4/8/2026
Status: Merged
Merged: 4/10/2026
Merged by: @james-elicx

Base: mainHead: fix/layout-generatemetadata-searchparams


📝 Commits (3)

  • 477032f fix(app-router): pass searchParams to layout generateMetadata
  • cb8051e test: update entry-templates snapshots for searchParams in layout generateMetadata
  • 15a3067 fix: match Next.js parity for layout generateMetadata searchParams

📊 Changes

5 files changed (+174 additions, -112 deletions)

View changed files

📝 packages/vinext/src/entries/app-rsc-entry.ts (+18 -16)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+108 -96)
📝 tests/app-router.test.ts (+14 -0)
tests/fixtures/app-basic/app/layout-metadata-search/layout.tsx (+26 -0)
tests/fixtures/app-basic/app/layout-metadata-search/page.tsx (+8 -0)

📄 Description

Summary

  • Layout generateMetadata() was always called with undefined for searchParams because the spObj (URLSearchParams → plain object conversion) was constructed after the layout metadata loop — only the page segment received the real query parameters.
  • Fix: hoist spObj construction to before the layout loop so all layouts receive the same search params object already correctly used by the page.
  • Adds a regression fixture (tests/fixtures/app-basic/app/layout-metadata-search/) and a test asserting that layout generateMetadata() title reflects the URL query parameter value, not the undefined-fallback default.

Root Cause

In packages/vinext/src/entries/app-rsc-entry.ts, the layout loop called:

resolveModuleMetadata(layoutMods[i], params, undefined, parentForThisLayout)

while the page call (a few lines later) correctly used spObj. The spObj variable simply wasn't constructed yet when the loop ran.

Test Plan

  • New test: layout generateMetadata() receives searchParams from URL query string — verifies ?tab=settings produces <title>Layout Section: settings</title> from the layout's generateMetadata
  • All existing metadata tests still pass (vp test run tests/app-router.test.ts -t "metadata|generateMetadata|viewport" — 26 tests green)
  • vp check passes (format, lint, types)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/793 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 4/8/2026 **Status:** ✅ Merged **Merged:** 4/10/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `fix/layout-generatemetadata-searchparams` --- ### 📝 Commits (3) - [`477032f`](https://github.com/cloudflare/vinext/commit/477032f4bb51bc6ca2e2e33f55e2f09280f75d97) fix(app-router): pass searchParams to layout generateMetadata - [`cb8051e`](https://github.com/cloudflare/vinext/commit/cb8051eccc221846f1f3553ee5316f85fe7502e1) test: update entry-templates snapshots for searchParams in layout generateMetadata - [`15a3067`](https://github.com/cloudflare/vinext/commit/15a306705aa2dcf1d9fc73ab665f40269aa97ec5) fix: match Next.js parity for layout generateMetadata searchParams ### 📊 Changes **5 files changed** (+174 additions, -112 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+18 -16) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+108 -96) 📝 `tests/app-router.test.ts` (+14 -0) ➕ `tests/fixtures/app-basic/app/layout-metadata-search/layout.tsx` (+26 -0) ➕ `tests/fixtures/app-basic/app/layout-metadata-search/page.tsx` (+8 -0) </details> ### 📄 Description ## Summary - Layout `generateMetadata()` was always called with `undefined` for `searchParams` because the `spObj` (URLSearchParams → plain object conversion) was constructed *after* the layout metadata loop — only the page segment received the real query parameters. - Fix: hoist `spObj` construction to before the layout loop so all layouts receive the same search params object already correctly used by the page. - Adds a regression fixture (`tests/fixtures/app-basic/app/layout-metadata-search/`) and a test asserting that `layout generateMetadata()` title reflects the URL query parameter value, not the undefined-fallback default. ## Root Cause In `packages/vinext/src/entries/app-rsc-entry.ts`, the layout loop called: ```ts resolveModuleMetadata(layoutMods[i], params, undefined, parentForThisLayout) ``` while the page call (a few lines later) correctly used `spObj`. The `spObj` variable simply wasn't constructed yet when the loop ran. ## Test Plan - [x] New test: `layout generateMetadata() receives searchParams from URL query string` — verifies `?tab=settings` produces `<title>Layout Section: settings</title>` from the layout's `generateMetadata` - [x] All existing metadata tests still pass (`vp test run tests/app-router.test.ts -t "metadata|generateMetadata|viewport"` — 26 tests green) - [x] `vp check` passes (format, lint, types) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:10:28 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#852
No description provided.