-
Notifications
You must be signed in to change notification settings - Fork 30k
Description
Verify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 22.5.0: Thu Jun 8 22:22:20 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T6000
Binaries:
Node: 18.16.0
npm: 9.5.1
Yarn: 1.22.19
pnpm: 8.6.10
Relevant Packages:
next: 13.4.13-canary.1
eslint-config-next: 13.4.13-canary.1
react: 18.2.0
react-dom: 18.2.0
typescript: 5.1.6
Next.js Config:
output: N/AWhich area(s) of Next.js are affected? (leave empty if unsure)
App Router
Link to the code that reproduces this issue or a replay of the bug
https://github.com/kachkaev/next-js-intercepting-routes-in-groups-mwe
Here is the ‘product spec’:
The app is a photo browser, similar to nextgram.
There are three navigation pages:
- Home page (recent photos)
- top photos
- best photo
When users navigate to a photo on the first two pages, it should open in a modal.
When users navigate to a photo on the third page, it should open in a new page, not in a modal.
Each photo page has previous / next links. Neighbouring photos open in the same way: in a modal or in a new page*.
* When I add previous / next links in the nextgram app, neighbouring photos always open in a modal. This creates modals on the standalone photo page, which is what I am trying to avoid:
nextrgram-previous-next.mp4
To Reproduce
-
Clone the repo:
git clone https://github.com/kachkaev/next-js-intercepting-routes-in-groups-mwe.git cd next-js-intercepting-routes-in-groups-mwe pnpm install pnpm dev -
Inspect the folder structure:
app/ ├── (no-modal) │ ├── best-photo │ │ └── page.tsx │ ├── layout.tsx │ └── photo │ └── page.tsx ├── (with-modal) │ ├── @modal │ │ ├── (...)photo │ │ │ └── page.tsx │ │ ├── page.tsx │ │ └── top-photos │ │ └── page.tsx │ ├── layout.tsx │ ├── page.tsx │ └── top-photos │ └── page.tsx └── layout.tsx
Here is the technical solution I have come up with based on the docs:
- There is a root layout for global navigation, CSS reset, custom fonts, etc.
- There are two route groups called
(no-modal)and(with-modal). - Home page and ‘top photos’ page are in the
(with-modal)group. - The layout file in this group contains a slot called
@modalwhich renders a photo page using an intercepting route. - The ‘best photo’ page is in the
(no-modal)group, together with the photo page itself. - In addition to the intercepting route for a photo,
app/(with-modal)/@modalalso contains dummy routes for the home page and the ‘top photos’ page to avoid 404s. I know it is possible to adddefaultorcatch-allroutes to this folder too, but doing so would blur the distinction between the two route groups and thus make the reproduction a bit less vivid.
The reproduction example does not use dynamic routes for simplicity. Photo ids are encoded in a GET param. Going for
photo/[id]produces the same results (see below). -
Open http://localhost:3000 and navigate between the home page and the ‘top photos’ page. Click on individual photo links within these pages and observe them opened in the modal, as expected. We are in the same route group called
(with-modal), all works fine so far.happy-path.mp4
-
Broken scenario 1: While on a photo page, press refresh in the browser. Observe that the photo page is opened in a new page, not in a modal. This is expected. Now try navigating to a previous or a next photo and observe an error:
Unhandled Runtime Error Error: notFound() is not allowed to use in root layoutbroken-scenario-1.mp4
-
Broken scenario 2: Navigate to the ‘best photo’ page and observe that it uses
(no-modal)layout, as expected. Navigate to a photo page and observe the same error as above.broken-scenario-2.mp4
-
Broken scenario 3: Open the photo page and observe that it uses
(no-modal)layout, as expected. Make a small tweak in/app/(no-modal)/photo/page.tsxto trigger hot reloading. ObservenotFound()error again:
Describe the Bug
Seems like Next.js is unable to deal with intercepting routes and route groups at the same time. Presence of app/(with-modal)/@modal/(...)photo/page.tsx breaks navigation to /photo from pages where this route is not intercepting.
The same happens for dynamic routes (i.e. when /photo?id=123 is replaced with /photo/123). See the PR #1 in the reproduction repo.
Expected Behavior
I would expect that the app would work according to product spec described earlier. The folder structure I have come up with seems to match Next.js docs for the listed requirements. Avoiding modals at least on the photo page is crucial and I am not sure how to do this without using route groups and intercepting routes.
Perhaps, this is just a matter of docs and I am just missing something. I have been trying various workarounds for quite a few hours last weekend but have not solved the problem no matter what I have tried. Hope that the reproduction example is helpful.
Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
I have not tried deploying this app yet, but if I try pnpm build && pnpm start, navigation remains broken in the same scenarios as during pnpm dev. There are two key differences:
- Error message says:
Application error: a server-side exception has occurred (see the server logs for more information). Digest: NEXT_NOT_FOUND - Unlike in
pnpm dev, browser URL does not update when a broken link is followed.
pnpm-build-start.mp4
PS: Despite this situation and some level of frustration caused by it, I find the new router pretty awesome. So let me use this bug report as an opportunity to thank the Next.js community for working on it! I know that some developers struggle with the new model because of the things they’ve got used to, but I do see a lot of value in the change! Epic stuff! 👏

