Hirefullstack – Software Engineering & IT-Beratung aus Berlin
← Back to overview
Advanced 11 min read

Parallel & intercepting routes

Two tools you rarely need – and then cannot do without

In one sentence

Parallel routes fill several areas of a page independently. Intercepting routes show an address as an overlay without leaving the page.

Good to know This one is optional

Most projects get by without either. But if one of these two jobs shows up, there is no good alternative – so it is worth knowing they exist.

Parallel routes: several areas at once

A dashboard has metrics, an activity feed and a team overview. All three take different times to load and should refresh independently. With Parallel routesSeveral areas of one page filled at the same time and independently of each other. Their folders start with `@`. each area gets its own file – and its own loading and error behaviour.

app/dashboard/
app/dashboard/
  layout.tsx        receives the areas as props
  page.tsx          the main area
  @metrics/
    page.tsx
    loading.tsx     its own placeholder
  @activity/
    page.tsx
    error.tsx       its own safety net
app/dashboard/layout.tsx
export default function Layout({
  children,
  metrics,
  activity,
}: {
  children: React.ReactNode;
  metrics: React.ReactNode;
  activity: React.ReactNode;
}) {
  return (
    <div className="grid">
      <section>{metrics}</section>
      <section>{activity}</section>
      <main>{children}</main>
    </div>
  );
}
The folder name after the @ becomes the prop name. children is the area without an @.
Tip The real win

Every area brings its own loading.tsx and error.tsx. If the activity feed fails, the rest of the dashboard still stands. With a normal page everything would break together.

Intercepting routes: the overlay

You know it from photo galleries: click a picture in the overview and it opens as an overlay – yet the address changes. Share that address and the recipient lands on a full page. That is what Intercepting routesCatching an address and showing it differently – a photo as an overlay rather than its own page, as long as you came from the list. does.

app/
app/
  gallery/
    page.tsx              the overview
    @modal/
      (.)photo/[id]/
        page.tsx          overlayintercepts clicks from the gallery
  photo/[id]/
    page.tsx              the real pageon a direct request
The bracket prefix picks the level: (.) same, (..) one up, (...) from the root.
sequence.txt
Click in the gallery       → address becomes /photo/42
                           → overlay opens, gallery stays behind
Reload the page            → the normal page at /photo/42
Address shared             → recipient sees the normal page
Back button                → overlay closes, gallery is still there
Pitfall Both versions have to exist

You need the intercepted and the normal page. Build only the overlay and a direct request gives a 404 – which is exactly what happens with every shared link.

When the effort pays off

Reach for it when …
  • +

    Dashboards whose areas load and fail independently

  • +

    Galleries and detail views that should appear as an overlay

  • +

    Sign-in dialogs that also have to work as a standalone page

Skip it when …
  • Simple dialogs with no address of their own – state is enough there

  • Areas that load together anyway

  • As the first thing in a project – exhaust the simple tools first

Careful Debugging gets harder

Folders with @, (.) and (..) take getting used to, and when an area does not show up the cause is often a missing default.tsx. Reach for these tools when you need them – not because they look interesting.

In more depth: default.tsx optional

With parallel routes it can happen that an area has no page for the current address. On a fresh load Next.js then does not know what to show there – and throws.

app/dashboard/@activity/default.tsx
// Steps in when this area has nothing for the current address.
export default function Default() {
  return null;      // or a sensible starting state
}
Tip The most common error at this point

If reloading a page with parallel routes makes something disappear or throw, a default.tsx is almost always missing in one of the @ folders. While navigating it goes unnoticed – only a direct request reveals it.

Does it stick?

4 questions on this lesson. Wrong answers show up in your stats.

Hirefullstack

Need React firepower on your team?

We have been building React and Next.js applications for clients across Germany for years – as a single expert, as reinforcement for an existing team, or as a complete Scrum team.

Talk about your project →