Advanced routes: parallel and intercepting
@ slots, default.tsx, intercepted routes and modals with their own URL.
Updated
What advanced routes are
Besides regular routes (Routing), the App Router has two conventions for complex interfaces:
| Convention | What it does | The classic example |
|---|---|---|
Parallel routes (@slot) |
renders several pages at once in the same layout, each independently navigable | a dashboard with panels, a sidebar + content with separate states |
Intercepting routes ((.)) |
shows a route in the context of the current page (usually as a modal), but keeps the real URL | clicking a photo in a feed → a modal; a refresh on the same URL → the photo's full page |
Parallel routes — slots
A folder that starts with @ is a slot. It doesn't appear in the URL; it's passed as a prop to the parent layout.
app/dashboard/layout.tsxreceives children, analytics and teampage.tsx/dashboard — the implicit children slot@analytics/page.tsxdefault.tsxwhat shows when the slot has no match
@team/page.tsxdefault.tsx
export default function DashboardLayout({ children, analytics, team }: LayoutProps<'/dashboard'>) {
return (
<div className="grid grid-cols-2 gap-6">
{children}
{analytics}
{team}
</div>
)
}| Detail | Why it matters |
|---|---|
each slot can have its own loading.tsx and error.tsx |
the panels load and fail independently |
default.tsx |
on a reload of a sub-route, slots without a match show default (otherwise: a 404) |
| slots don't affect the URL | @analytics/views → /dashboard/views |
Good for conditional display too: the layout picks {isAdmin ? admin : user}.
Intercepting routes — a modal with a URL
app/feed/page.tsxthe list of photos
photo/[id]/page.tsxthe photo's full page — on a refresh or a direct link
@modal/default.tsxreturn null — no modal by default(.)photo/[id]/page.tsxthe same photo, as a modal over the feed
layout.tsxrenders children + modal
| Marker | Intercepts the segment |
|---|---|
(.) |
on the same level |
(..) |
one level up |
(..)(..) |
two levels up |
(...) |
from the app root |
The levels are route segments, not folders — @modal slots don't count.
The behavior:
| Action | Result |
|---|---|
clicking <Link href="/photo/7"> in the feed |
the URL becomes /photo/7, the modal opens over the feed |
| a refresh / a link sent to someone | the full page /photo/7 shows |
| Back / closing | router.back() — the modal disappears, the feed is intact |
Exactly how photos work on Instagram or products on a shopping site.
When to use them
- Parallel: interfaces with independent areas (a dashboard, an inbox with a list + detail), tabs with their own URL.
- Intercepting: modals that must be shareable as a link (a product preview, a photo, a login over the current page).
- Otherwise: simple routes — they're easier to understand.
Summary
@slot= pages rendered in parallel, a prop on the layout, withdefault.tsx.(.)/(..)/(...)= an intercepted route, usually as a modal, with a real URL.- A modal with a URL: an
@modalslot + an intercepted route +router.back()on close.