DEV Community

Cover image for πŸš€ Parallel Routes & Intercepting Routes in Next.js β€” Complete Beginner-Friendly Guide
Vishwark
Vishwark

Posted on

πŸš€ Parallel Routes & Intercepting Routes in Next.js β€” Complete Beginner-Friendly Guide

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}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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}</>;
}
Enter fullscreen mode Exit fullscreen mode

βœ” Correct place:

// layout.tsx
export default function RootLayout({ children, modal }) {
  return (
    <>
      {children}
      {modal}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Desired UX:

  • Modal only when user comes from profile

Folder:

@modal/(..)settings/profile/edit/page.tsx
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Intercept only when navigation comes from /dashboard/users:

@modal/(..)(..)dashboard/users/[id]/page.tsx
Enter fullscreen mode Exit fullscreen mode

4️⃣ (...) β€” Root-Level Interception

Useful for global modals like /login and /signup.

@modal/(...)login/page.tsx
Enter fullscreen mode Exit fullscreen mode

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

  • /login should 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/confirm Where 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)