C.W.K.
Stream
Lesson 08 of 10 · published

Intercepting Routes

~22 min · intercepting routes, modal, overlay

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

The Instagram pattern

Click a photo in a feed: a modal opens with the photo. Refresh the page on that URL: you get a full page view of the photo. Same URL, two presentations. Intercepting routes makes this declarative.

The conventions

PrefixMeans "intercept from"
(.)same level segment
(..)one level up
(..)(..)two levels up
(...)app root

The pattern in code

Use intercepting routes together with parallel routes (@modal) to render the modal version inside the current layout while preserving the deep-link page for refresh/share.

Code

Folder layout for the photo modal·text
app/
├── layout.tsx
├── page.tsx                                  # /
├── @modal/
│   ├── default.tsx                           # nothing by default
│   └── (.)photos/[id]/page.tsx               # intercepts /photos/:id
├── photos/
│   └── [id]/page.tsx                         # full page view
└── feed/page.tsx                             # /feed (links to /photos/:id)
Intercepted page renders as a modal·tsx
// app/@modal/(.)photos/[id]/page.tsx
import { Modal } from '@/components/Modal';

export default async function PhotoModal({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const photo = await getPhoto(id);

  return (
    <Modal closeHref="/feed">
      <img src={photo.url} alt={photo.title} className="max-h-[70vh]" />
      <p className="text-sm mt-2">{photo.title}</p>
    </Modal>
  );
}
Direct nav still gets the full page·tsx
// app/photos/[id]/page.tsx
export default async function PhotoPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const photo = await getPhoto(id);
  return (
    <main className="p-8">
      <img src={photo.url} alt={photo.title} className="w-full max-h-[80vh] object-contain" />
      <h1 className="text-2xl mt-4">{photo.title}</h1>
      <p className="mt-2 text-gray-600">{photo.description}</p>
    </main>
  );
}

External links

Exercise

Add a feed page that links to /photos/:id. Build the intercepting route so clicking a thumbnail opens a modal but pasting the URL into a fresh tab loads the full photo page.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.