Intercepting routes
This page explains how to implement route interception in Next.js to load content from another route while preserving the current context.
Understanding intercepting routes
Intercepting routes allows you to show content from a different route while maintaining the current layout and UI state. This pattern enables advanced UX patterns like modal overlays that:
- Preserve the current page context
- Update the URL to match the intercepted content
- Maintain a shareable/bookmarkable URL
- Work correctly on page refresh
Intercepting routes conventions
Next.js provides special naming conventions for route interception:
(.)
- Match segments at same level(..)
- Match segments one level above(..)(..)
- Match segments two levels above(...)
- Match segments from root
Same level (.)
Suppose we have the following file structure and we want to intercept the route /f1/f2
from /f1
:
Directoryapp/
Directoryf1/ source route
- page.tsx
Directoryf2/ target route
- page.tsx
- Start in your source route directory
app/f1/
and create a new folder that will contain your intercepting page:app/f1/prefix_intercepting-folder/page.tsx
- Name the folder the same as the target route
f2
:app/f1/prefix_f2/page.tsx
- Add the prefix
(.)
sincef2
andprefix_f2
are at the same level:app/f1/(.)f2/page.tsx
Directoryapp/
Directoryf1/ source route
- page.tsx
Directory(.)f2/ intercepting route
- page.tsx
Directoryf2/ target route
- page.tsx
import Link from "next/link";
export default function F1() { return ( <> <h1>F1 page</h1> <Link href="/f1/f2">Go to F2</Link> </> );}
export default function F2() { return <h1>F2 page</h1>;}
// Interceptor: app/f1/(.)f2/page.tsxexport default function InterceptedF2() { return <h1>(.) Intercepted F2 page</h1>;}
When a user clicks a link to /f1/f2
from the /f1
page:
- The URL changes to
/f1/f2
- The
(.)f2
intercepting route is shown to the user - On page refresh, the actual
f2
route is shown instead
One level up (..)
Suppose we have the following file structure and we want to intercept the route /f3
from /f1
:
Directoryapp/
Directoryf1/ source route
- page.tsx
Directoryf3/ target route
- page.tsx
- Start in your source route directory
app/f1/
and create a new folder that will contain your intercepting page:app/f1/prefix_intercepting-folder/page.tsx
- Name the folder the same as the target route
f3
:app/f1/prefix_f3/page.tsx
- Add the prefix
(..)
sincef3
is one level up fromf1
:app/f1/(..)f3/page.tsx
Directoryapp/
Directoryf1/ source route
- page.tsx
Directory(..)f3/ intercepting route
- page.tsx
Directoryf3/ target route
- page.tsx
import Link from "next/link";
export default function F1() { return ( <> <h1>F1 page</h1> <Link href="/f3">Go to F3</Link> </> );}
export default function F3() { return <h1>F3 page</h1>;}
// Interceptor: app/f1/(..)f3/page.tsxexport default function InterceptedF3() { return <h1>(..) Intercepted F3 page</h1>;}
When a user clicks a link to /f3
from the /f1
page:
- The URL changes to
/f3
- The
(..)f3
intercepting route is shown to the user - On page refresh, the actual
f3
route is shown instead
Two levels up (..)(..)
Suppose we have the following file structure and we want to intercept the route /f4
from /f1/f2
:
Directoryapp/
Directoryf1/
Directoryf2/ source route
- page.tsx
Directoryf4/ target route
- page.tsx
- Start in your source route directory
app/f1/f2/
and create a new folder that will contain your intercepting page:app/f1/f2/prefix_intercepting-folder/page.tsx
- Name the folder the same as the target route
f4
:app/f1/f2/prefix_f4/page.tsx
- Add the prefix
(..)(..)
sincef4
is two levels up fromf2
:app/f1/f2/(..)(..)f4/page.tsx
Directoryapp/
Directoryf1/
Directoryf2/ source route
- page.tsx
Directory(..)(..)f4/ intercepting route
- page.tsx
Directoryf4/ target route
- page.tsx
import Link from "next/link";
export default function F2() { return ( <> <h1>F2 page</h1> <Link href="/f4">Go to F4</Link> </> );}
export default function F4() { return <h1>F4 page</h1>;}
// Interceptor: app/f1/f2/(..)(..)f4/page.tsxexport default function InterceptedF4() { return <h1>(..)(..) Intercepted F4 page</h1>;}
When a user clicks a link to /f4
from the /f1/f2
page:
- The URL changes to
/f4
- The
(..)(..)f4
intercepting route is shown to the user - On page refresh, the actual
f4
route is shown instead
Root level (…)
Suppose we have the following file structure and we want to intercept the route /f5
from /f1/f2/inner-f2
:
Directoryapp/
Directoryf1/
Directoryf2/
Directoryinner-f2/ source route
- page.tsx
Directoryf5/ target route
- page.tsx
- Start in your source route directory
app/f1/f2/inner-f2/
and create a new folder that will contain your intercepting page:app/f1/f2/inner-f2/prefix_intercepting-folder/page.tsx
- Name the folder the same as the target route
f5
:app/f1/f2/inner-f2/prefix_f5/page.tsx
- Add the prefix
(...)
to match from root:app/f1/f2/inner-f2/(...)f5/page.tsx
Directoryapp/
Directoryf1/
Directoryf2/
Directoryinner-f2/ source route
- page.tsx
Directory(…)f5/ intercepting route
- page.tsx
Directoryf5/ target route
- page.tsx
import Link from "next/link";
export default function InnerF2() { return ( <> <h1>Inner F2 page</h1> <Link href="/f5">Go to F5</Link> </> );}
export default function F5() { return <h1>F5 page</h1>;}
// Interceptor: app/f1/f2/inner-f2/(...)f5/page.tsxexport default function InterceptedF5() { return <h1>(...) Intercepted F5 page</h1>;}
When a user clicks a link to /f5
from the /f1/f2/inner-f2
page:
- The URL changes to
/f5
- The
(...)f5
intercepting route is shown to the user - On page refresh, the actual
f5
route is shown instead
File structure overview
Directoryapp/
Directoryf1/
Directory(.)f2/ // same level
- page.tsx
Directory(..)f3/ // one level up
- page.tsx
Directoryf2/
Directory(..)(..)f4/ // two levels up
- page.tsx
Directoryinner-f2/
- page.tsx
Directory(…)f5/ // root level
- page.tsx
Directoryf3/
- page.tsx
Directoryf4/
- page.tsx
Directoryf5/
- page.tsx
This structure shows how: (.) matches at the same level (f1 → f2) (..) matches one level up (f1 → f3) (..)(..) matches two levels up (f2 → f4) (…) matches from root (inner-f2 → f5) Each prefix is determined by the relationship between the source route (where the link is) and the target route (where we’re navigating to).
Common use cases
Route interception is particularly useful for:
- Photo/video modals in galleries
- Authentication flows
- Product quick-views in e-commerce
- Expanded post views in social feeds
Good to know
- Intercepted routes maintain shareable URLs
- Original layout/context is preserved
- Works with browser back/forward navigation