Next.js App Router introduced two advanced routing primitives:
- Parallel Routes
- Intercepting Routes
These arenβt random features β they were invented to solve challenges that naturally arise in file-based routing.
This guide explains Parallel Routes from scratch (no use case at first), then naturally introduces the real-world modal use case, shows why Parallel Routes fail alone, and how Intercepting Routes solve that problem. Finally, weβll cover all interception patterns (.), (..), (..)(..), (...) with real URLs β and end with practical use cases.
Letβs begin.
π¦ 1. What Are Parallel Routes?
Parallel Routes allow a layout to render multiple independent route segments at the same time.
Example layout:
export default function RootLayout({ children, modal }) {
return (
<>
{children}
{modal}
</>
);
}
This layout expects two branches:
-
childrenβ normal page content -
modalβ secondary UI (modal/sidebar/etc.)
Folder Structure
app/
ββ layout.tsx
ββ page.tsx
ββ @modal/
ββ default.tsx
ββ settings/page.tsx
Visiting /
- children β page.tsx
- modal β default.tsx
Visiting /settings
- children β still page.tsx
- modal β settings/page.tsx
No modals yet. No use-case assumed.
Parallel routes simply let you render two active routes simultaneously.
π© 2. Important Nuance β Modal Slots Must Be in a Layout, Not a Page
Parallel route slots (modal, sidebar, feed) only work in layout.tsx.
They DO NOT work in page.tsx.
This is a common mistake:
β This will NEVER work:
export default function Page({ modal }) {
return <>{modal}</>;
}
β Correct place:
// layout.tsx
export default function RootLayout({ children, modal }) {
return (
<>
{children}
{modal}
</>
);
}
Parallel routes are injected only into layouts.
π₯ 3. Introducing the Real Use Case
Most real apps want this behavior:
β Internal navigation β show modal
/posts β /posts/42 β modal over the list
β Direct URL or refresh β show full page
/posts/42 β full-page view
This is how:
- Instagram post modals
- Twitter image modals
- YouTube video modals
- Airbnb listing modals
all work.
Let's see why parallel routes fail for this use case.
π₯ 4. Why Parallel Routes Fail Alone
Folder you might create:
app/
ββ posts/page.tsx
ββ posts/[id]/page.tsx
ββ @modal/
ββ default.tsx
ββ posts/[id]/page.tsx
Scenario 1 β /posts β /posts/42
Matches:
- children β full page
- modal β modal version
β Renders both β wrong.
Scenario 2 β reload /posts/42
Same matches:
- children β full page
- modal β modal version
β Shows both on refresh β wrong.
Scenario 3 β open /posts/42 directly
Same matches again
β wrong behavior.
Why?
Because parallel routes match purely based on the filesystem, not on navigation context.
They cannot know:
- Did user come from
/posts? - Did user refresh?
- Did user open the URL directly?
- Did user come from another screen?
They ALWAYS show the modal if the route exists.
So parallel routes alone are not enough.
π¦ 5. The Fix β Intercepting Routes
Intercepting Routes let you control when a route should render.
Correct folder structure:
app/
ββ posts/page.tsx
ββ posts/[id]/page.tsx
ββ @modal/
ββ default.tsx
ββ (.)posts/[id]/page.tsx
That (.) prefix tells Next.js:
βUse THIS version ONLY on internal navigation from the same route level.β
And suddenly everything behaves correctly:
| Scenario | children | modal |
|---|---|---|
/posts β /posts/42 |
list stays | modal appears |
reload /posts/42
|
full page | empty |
/home β /posts/42 |
full page | empty |
open /posts/42 directly |
full page | empty |
Parallel + Intercepting Routes give you PERFECT modal UX.
πͺ 6. All Intercepting Route Prefixes Explained (With Real URLs)
Next.js provides 4 interception patterns.
Letβs use real URLs to understand them.
1οΈβ£ (.) β Same-Level Interception
Working folder:
@modal/(.)posts/[id]/page.tsx
Works for:
/posts β /posts/42 β modal β
Does NOT intercept:
refresh /posts/42
/home β /posts/42
This is the most common form.
2οΈβ£ (..) β One Level Up
Example URLs:
/settings/profile
/settings/profile/edit
/settings/edit
Desired UX:
- Modal only when user comes from profile
Folder:
@modal/(..)settings/profile/edit/page.tsx
Works:
/settings/profile β /settings/profile/edit β modal β
Does NOT:
/settings β /settings/profile/edit
refresh /settings/profile/edit
3οΈβ£ (..)(..) β Two Levels Up
Useful for deep URLs.
Example:
/dashboard/users
/dashboard/users/42
/dashboard/users/42/edit
Intercept only when navigation comes from /dashboard/users:
@modal/(..)(..)dashboard/users/[id]/page.tsx
4οΈβ£ (...) β Root-Level Interception
Useful for global modals like /login and /signup.
@modal/(...)login/page.tsx
Works (modal):
/home β /login
/posts β /login
Does NOT intercept:
refresh /login β full page
direct /login β full page
π 7. Real Use Cases Where Youβll Use These Features
Here are the most common scenarios where Parallel + Intercepting Routes shine:
1. Modal Detail View Over a List Page
/posts-
/posts/[id](modal over list) - reload
/posts/[id]β full page This is the Instagram/Twitter/YouTube pattern.
2. Nested Settings With Modal Editor
Routes:
/settings/profile-
/settings/profile/edit(modal) -
/settings/edit(full page) Perfect for complex dashboards.
3. Global Login Modal
-
/loginshould be a modal when navigating internally - But a full page when visited directly Useful for onboarding flows.
4. Sidebar + Content + Modal All Active at Once
Parallel routes let you render:
- sidebar
- content
- modal each as independent routes.
5. Split View Apps (Inbox, Email, Admin UI)
Like Gmail:
/inbox-
/inbox/[id](preview) -
/inbox/[id]/details(modal or separate pane)
Parallel routes allow multiple panes to be alive simultaneously.
6. Music/Video Player That Stays While Navigating
Parallel route (player) + main route (content).
7. Multi-Step Flows With Side Panels
/reports/reports/create-
/reports/create/confirmWhere parts of UI should stay alive as separate routes.
π§ Final Mental Model
β Parallel Routes
Keep multiple routes alive.
Good for: layout slots (sidebar, modal, feed, toolbar).
β But parallel routes ALWAYS match filesystem
Bad for modal behavior: duplicate content on reload.
β Intercepting Routes
Decide when to show modal:
- on internal navigation β modal
- on reload/direct link β full page
β Prefixes
-
(.)same-level -
(..)one level up -
(..)(..)two levels up -
(...)root-level
β Parallel route slot must be inside a layout, not inside a page
Conclusion π¨π»βπ
Parallel Routes let you keep multiple route segments alive, and Intercepting Routes make them behave correctly by activating route only when appropriate. Together, they deliver the modern, context-aware routing experience that file-based routing cannot provide on its own β thanks for reading!
Top comments (0)