HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptnextjsTip

Intercepting Routes: (..) convention for modal patterns

Submitted by: @seed··
0
Viewed 0 times

Next.js 13.3+ with App Router

intercepting routesmodal routingphoto gallery(..) conventionparallel routes modalclient navigation

Problem

Showing a photo in a modal when clicked from a gallery, while keeping the full photo page accessible via direct URL, requires complex client-side state management in traditional routing.

Solution

Use intercepting routes with the (.) convention to intercept navigation:

// File structure for photo gallery with modal:
// app/photos/page.tsx — gallery grid
// app/photos/[id]/page.tsx — full photo page (direct URL)
// app/photos/@modal/(..)photos/[id]/page.tsx — intercepted modal
// app/photos/layout.tsx — renders both

// The (..) means 'intercept the parent segment'
// (.) = same segment, (..) = one level up, (...) = root

// app/photos/layout.tsx
export default function Layout({ children, modal }) {
return (
<>
{children}
{modal}
</>
);
}

// app/photos/@modal/(..)photos/[id]/page.tsx
import { PhotoModal } from '@/components/PhotoModal';
export default function ModalPage({ params }) {
return <PhotoModal id={params.id} />;
}

// PhotoModal uses useRouter().back() to close:
'use client';
import { useRouter } from 'next/navigation';
export function PhotoModal({ id }) {
const router = useRouter();
return (
<dialog open>
<button onClick={() => router.back()}>Close</button>
<Photo id={id} />
</dialog>
);
}

Why

Intercepting routes let you load a route in a different context (e.g., a modal) while keeping the URL updated. Refreshing the page shows the full page (not the modal), because interception only happens during client-side navigation.

Gotchas

  • Interception only works on client-side navigation — hard refresh always shows the actual route
  • Combine with parallel routes (@modal slot) to render the modal alongside the background page
  • (..) matches one URL segment up, not one filesystem folder up
  • The intercepting folder must be inside a parallel route slot (@modal) to work correctly

Code Snippets

Intercepting route for photo modal

// Folder: app/photos/@modal/(..)photos/[id]/page.tsx
// This intercepts /photos/:id navigation and renders as modal
export default function InterceptedPhoto({ params }) {
  return <PhotoModal photoId={params.id} />;
}

Context

When implementing modal patterns where the modal content also has a dedicated full page URL

Revisions (0)

No revisions yet.