[PR #867] [MERGED] Fix sibling intercepted App Router routes #906

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

📋 Pull Request Information

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

Base: mainHead: fix/sibling-interception


📝 Commits (5)

  • 5867692 fix app router sibling interception
  • 41e913f update app router entry snapshots
  • 0413015 preserve chained intercepted navigations
  • 1d1abf1 address intercepted route review feedback
  • 6e727ee guard probePage() against undefined PageComponent for slot-only routes

📊 Changes

21 files changed (+475 additions, -51 deletions)

View changed files

📝 packages/vinext/src/entries/app-rsc-entry.ts (+29 -7)
📝 packages/vinext/src/routing/app-router.ts (+50 -2)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+174 -42)
📝 tests/e2e/app-router/advanced.spec.ts (+64 -0)
tests/fixtures/app-basic/app/film/[imdbId]/page.tsx (+8 -0)
tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@feed/default.tsx (+5 -0)
tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@feed/page.tsx (+12 -0)
tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@modal/(..)photo/[id]/page.tsx (+3 -0)
tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@modal/default.tsx (+3 -0)
tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/layout.tsx (+15 -0)
tests/fixtures/app-basic/app/parallel-sibling-modal/photo/[id]/page.tsx (+3 -0)
tests/fixtures/app-basic/app/sibling-source/@modal/(..)sibling-target/[id]/page.tsx (+8 -0)
tests/fixtures/app-basic/app/sibling-source/@modal/default.tsx (+3 -0)
tests/fixtures/app-basic/app/sibling-source/layout.tsx (+14 -0)
tests/fixtures/app-basic/app/sibling-source/page.tsx (+12 -0)
tests/fixtures/app-basic/app/sibling-target/[id]/page.tsx (+7 -0)
tests/fixtures/app-basic/app/top/@modal/(..)film/[imdbId]/page.tsx (+8 -0)
tests/fixtures/app-basic/app/top/@modal/default.tsx (+3 -0)
tests/fixtures/app-basic/app/top/layout.tsx (+14 -0)
tests/fixtures/app-basic/app/top/page.tsx (+12 -0)

...and 1 more files

📄 Description

Summary

Fixes sibling intercepted App Router navigation when the source route is a layout-owned parallel-slot route.

This now matches the Next.js intercepting-parallel-modal reference shape where /[username] renders @feed and @modal, and navigating to a sibling target mounts the modal while preserving source content.

Fixes #866

What Changed

  • Discover layout routes whose own renderable content comes from parallel slot pages, even when the segment has no child page.tsx.
  • Allow the App Router RSC entry to render slot-only routes without treating them as “Page has no default export”.
  • Merge params from the source interception context with params from the target URL so preserved source slots keep source-only params.
  • Added regression fixtures for simple sibling (..), the reported /top to /film/[imdbId] shape, and the Next.js @feed + @modal/(..)photo/[id] shape.

Why It Matters

Apps using modal/detail routes from a listing page can now keep the listing tree mounted while rendering the intercepted sibling route. Source params such as username no longer disappear when they are not present in the target URL.

Risks Or Limits

This changes route discovery for layout segments with parallel slots but no child page. The added route is only created when that layout owns parallel slots and no existing route pattern already exists.

Verification

  • npx vp test run tests/routing.test.ts -t "layout routes whose own content is parallel slot pages"
  • npx vp test run tests/app-router.test.ts -t "intercept"
  • PLAYWRIGHT_PROJECT=app-router npx playwright test tests/e2e/app-router/advanced.spec.ts -g "sibling|top-level"
  • npx vp check packages/vinext/src/routing/app-router.ts packages/vinext/src/entries/app-rsc-entry.ts tests/routing.test.ts tests/e2e/app-router/advanced.spec.ts tests/fixtures/app-basic/app/sibling-source tests/fixtures/app-basic/app/sibling-target tests/fixtures/app-basic/app/top tests/fixtures/app-basic/app/film tests/fixtures/app-basic/app/parallel-sibling-modal

🔄 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/867 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 4/21/2026 **Status:** ✅ Merged **Merged:** 4/21/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `fix/sibling-interception` --- ### 📝 Commits (5) - [`5867692`](https://github.com/cloudflare/vinext/commit/5867692f700e1e916571b2c17494b76d29f2a3c5) fix app router sibling interception - [`41e913f`](https://github.com/cloudflare/vinext/commit/41e913f463a540b17b950897407f13f692444445) update app router entry snapshots - [`0413015`](https://github.com/cloudflare/vinext/commit/0413015b653f9c5b0225a57f56dfe2651050aedf) preserve chained intercepted navigations - [`1d1abf1`](https://github.com/cloudflare/vinext/commit/1d1abf10ce3eab2068499a842e8e1ffb25016fe5) address intercepted route review feedback - [`6e727ee`](https://github.com/cloudflare/vinext/commit/6e727ee5e7d16378e83fe76bf6cf0fb1e454d870) guard probePage() against undefined PageComponent for slot-only routes ### 📊 Changes **21 files changed** (+475 additions, -51 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+29 -7) 📝 `packages/vinext/src/routing/app-router.ts` (+50 -2) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+174 -42) 📝 `tests/e2e/app-router/advanced.spec.ts` (+64 -0) ➕ `tests/fixtures/app-basic/app/film/[imdbId]/page.tsx` (+8 -0) ➕ `tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@feed/default.tsx` (+5 -0) ➕ `tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@feed/page.tsx` (+12 -0) ➕ `tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@modal/(..)photo/[id]/page.tsx` (+3 -0) ➕ `tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/@modal/default.tsx` (+3 -0) ➕ `tests/fixtures/app-basic/app/parallel-sibling-modal/[username]/layout.tsx` (+15 -0) ➕ `tests/fixtures/app-basic/app/parallel-sibling-modal/photo/[id]/page.tsx` (+3 -0) ➕ `tests/fixtures/app-basic/app/sibling-source/@modal/(..)sibling-target/[id]/page.tsx` (+8 -0) ➕ `tests/fixtures/app-basic/app/sibling-source/@modal/default.tsx` (+3 -0) ➕ `tests/fixtures/app-basic/app/sibling-source/layout.tsx` (+14 -0) ➕ `tests/fixtures/app-basic/app/sibling-source/page.tsx` (+12 -0) ➕ `tests/fixtures/app-basic/app/sibling-target/[id]/page.tsx` (+7 -0) ➕ `tests/fixtures/app-basic/app/top/@modal/(..)film/[imdbId]/page.tsx` (+8 -0) ➕ `tests/fixtures/app-basic/app/top/@modal/default.tsx` (+3 -0) ➕ `tests/fixtures/app-basic/app/top/layout.tsx` (+14 -0) ➕ `tests/fixtures/app-basic/app/top/page.tsx` (+12 -0) _...and 1 more files_ </details> ### 📄 Description ## Summary Fixes sibling intercepted App Router navigation when the source route is a layout-owned parallel-slot route. This now matches the Next.js `intercepting-parallel-modal` reference shape where `/[username]` renders `@feed` and `@modal`, and navigating to a sibling target mounts the modal while preserving source content. Fixes #866 ## What Changed - Discover layout routes whose own renderable content comes from parallel slot pages, even when the segment has no child `page.tsx`. - Allow the App Router RSC entry to render slot-only routes without treating them as “Page has no default export”. - Merge params from the source interception context with params from the target URL so preserved source slots keep source-only params. - Added regression fixtures for simple sibling `(..)`, the reported `/top` to `/film/[imdbId]` shape, and the Next.js `@feed` + `@modal/(..)photo/[id]` shape. ## Why It Matters Apps using modal/detail routes from a listing page can now keep the listing tree mounted while rendering the intercepted sibling route. Source params such as `username` no longer disappear when they are not present in the target URL. ## Risks Or Limits This changes route discovery for layout segments with parallel slots but no child page. The added route is only created when that layout owns parallel slots and no existing route pattern already exists. ## Verification - `npx vp test run tests/routing.test.ts -t "layout routes whose own content is parallel slot pages"` - `npx vp test run tests/app-router.test.ts -t "intercept"` - `PLAYWRIGHT_PROJECT=app-router npx playwright test tests/e2e/app-router/advanced.spec.ts -g "sibling|top-level"` - `npx vp check packages/vinext/src/routing/app-router.ts packages/vinext/src/entries/app-rsc-entry.ts tests/routing.test.ts tests/e2e/app-router/advanced.spec.ts tests/fixtures/app-basic/app/sibling-source tests/fixtures/app-basic/app/sibling-target tests/fixtures/app-basic/app/top tests/fixtures/app-basic/app/film tests/fixtures/app-basic/app/parallel-sibling-modal` --- <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:46 +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#906
No description provided.