0Pricing
Next.js 15 Fullstack (App Router + Server Actions) · Lesson

Building a Photo-Modal Flow with Soft Navigation

Combine interception and parallel routes to open items in a modal yet deep-link on refresh.

Why Modals Break Deep-Linking

Traditional modal implementations render a dialog on top of the current page. This creates a fundamental problem: when a user shares the URL or refreshes the browser, the modal disappears — there is no route change, so no persistent URL state exists.

Next.js 15 solves this with two advanced routing features working in tandem:

  • Intercepting Routes — catch a navigation and render a different UI in the current context
  • Parallel Routes — render two route segments simultaneously in the same layout

Together they let you open a photo in a modal with a proper URL (e.g. /photos/42) while keeping the grid visible behind it. On a hard refresh, the same URL shows the full-page photo view instead.

The File Structure You Need

The pattern requires a specific directory layout inside your app/ folder. Here is the structure for a photo gallery:

  • app/photos/page.tsx — the photo grid (list view)
  • app/photos/[id]/page.tsx — the standalone full-page photo detail
  • app/@modal/(.)photos/[id]/page.tsx — the intercepted modal version
  • app/layout.tsx — root layout that accepts the modal slot

The @modal prefix declares a parallel route slot. The (.) prefix on the intercepting segment tells Next.js: intercept navigations that go to photos/[id] at the same depth in the URL tree.

This dual existence — a real page at photos/[id] and an intercepted version at @modal/(.)photos/[id] — is the entire secret.

All lessons in this course

  1. Parallel Routes with Named Slots and Default Segments
  2. Intercepting Routes for Shared Modal Experiences
  3. Conditional Slot Rendering for Dashboards and Tabs
  4. Building a Photo-Modal Flow with Soft Navigation
← Back to Next.js 15 Fullstack (App Router + Server Actions)