Parallel routes and intercepting routes in Next.js
What are Parallel Routes?
Parallel routes allow you to render multiple pages simultaneously in the same layout. They're defined using named slots with the @folder convention.
Basic Syntax
app/
layout.tsx
page.tsx
@sidebar/
page.tsx
@feed/
page.tsx// app/layout.tsx β receives parallel routes as props
export default function Layout({
children,
sidebar,
feed,
}: {
children: React.ReactNode;
sidebar: React.ReactNode;
feed: React.ReactNode;
}) {
return (
<div className="grid grid-cols-[250px_1fr]">
<aside>{sidebar}</aside>
<main>
{children}
{feed}
</main>
</div>
);
}Use Cases
1. Dashboard with Independent Panels
app/dashboard/
layout.tsx
page.tsx β main content
@stats/
page.tsx β statistics panel
loading.tsx β independent loading state
@notifications/
page.tsx β notifications panel
error.tsx β independent error boundaryEach slot can have its own loading and error states:
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
stats,
notifications,
}: {
children: React.ReactNode;
stats: React.ReactNode;
notifications: React.ReactNode;
}) {
return (
<div>
<div className="main">{children}</div>
<div className="sidebar">
{stats}
{notifications}
</div>
</div>
);
}2. Conditional Rendering (Auth)
// app/layout.tsx
import { getUser } from "@/lib/auth";
export default async function Layout({
children,
dashboard,
login,
}: {
children: React.ReactNode;
dashboard: React.ReactNode;
login: React.ReactNode;
}) {
const user = await getUser();
return user ? dashboard : login;
}What are Intercepting Routes?
Intercepting routes let you load a route within the current layout while showing a different URL. Common pattern: clicking a photo opens a modal, but navigating directly shows a full page.
Convention
(.)route β intercept same level
(..)route β intercept one level up
(..)(..)route β intercept two levels up
(...)route β intercept from rootPhoto Modal Example
app/
feed/
page.tsx β /feed (shows photo grid)
@modal/
(.)photo/[id]/
page.tsx β Intercepted: opens modal
default.tsx β null (no modal by default)
photo/
[id]/
page.tsx β /photo/123 (full page, direct navigation)// app/feed/@modal/(.)photo/[id]/page.tsx
// When navigating from /feed, this intercepts and shows a modal
export default async function PhotoModal({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const photo = await getPhoto(id);
return (
<Modal>
<img src={photo.url} alt={photo.title} />
</Modal>
);
}
// app/photo/[id]/page.tsx
// Direct navigation (/photo/123) shows the full page
export default async function PhotoPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const photo = await getPhoto(id);
return (
<div className="full-page">
<img src={photo.url} alt={photo.title} />
<PhotoDetails photo={photo} />
</div>
);
}Behavior Summary
| Feature | Parallel Routes | Intercepting Routes |
|---|---|---|
| Purpose | Render multiple pages in one layout | Show route in current context (modal) |
| Convention | @folder | (.), (..), (...) |
| URL | Same URL, multiple views | Changes URL but stays in current layout |
| Use case | Dashboards, conditional layouts | Modals, preview panels |
Important:
Parallel routes enable multi-panel layouts where each panel can load, error, and navigate independently. Intercepting routes create modal-like experiences (Instagram-style photo modals). Together, they're powerful for complex UIs that show multiple pieces of content simultaneously.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.