Andi Smith

Technical Leader Product Engineer AI Consultant

Mastering NextJS Parallel Routes

  • By Andi Smith
  • 5 minute read

Recently I came across a powerful routing feature in Next.js that completely changed how I thought about structured complex web applications.

I had an application where there were multiple components which needed to load and change independently. My use case was more than just needing different props - I essentially needed to have multiple children that sat in different parts of my layout.

And that's when I discovered NextJS Parallel Routes, which were introduced in NextJS 14.

What Are Parallel Routes?

Parallel Routes are an advanced routing mechanism that lets you show multiple pages at once within the same layout.

In regular websites, when you click a link, the whole page changes. But with Parallel Routes, only certain parts change while others stay the same. This is perfect for:

  • Data-heavy dashboards where you need to see multiple sections
  • An e-commerce site where you want to show products and a trolley independently
  • Social media feeds with different content types
  • Authentication flows where only part of the page changes when the user is logged in

How Do Parallel Routes Work?

The magic of Parallel Routes happens with special folders known as 'slots' which are prefixed with an @ symbol. For example @analytics. Let's say you're building a dashboard with three sections:

  1. Main dashboard
  2. Analytics section
  3. Revenue section

Here's how you'd set up your folder structure:

app/
└── dashboard/
    ├── layout.tsx
    ├── page.tsx (Main dashboard page)
    ├── @analytics/
    │   └── page.tsx (Analytics section)
    └── @revenue/
        └── page.tsx (Revenue section)

These slots automatically become props that are passed to the layout - you don't need to import them. So you can use them like so:

export default function DashboardLayout({
  children,
  analytics,
  revenue,
}) {
  return (
    <div>
      <nav>Dashboard Links</nav>
      <div>{children}</div>
      <div>{analytics}</div>
      <div>{revenue}</div>
    </div>
  );
}

Now you understand how they work, let's take a look at some of the cool things you can do with them:

1. Independent Loading and Error States

NextJS's App Router already has great handling for loading states, and this is extended with parallel routes which are able to have their own loading states!

This enables you to partially load your page and allow your users to interact even while other sections are still loading. Like you would for any NextJS loading state you can add loading to parallel route by simply adding a loading.tsx file inside each folder. e.g:

app/dashboard/@analytics/loading.tsx
app/dashboard/@revenue/loading.tsx

The same is the case for error handling. Just add an error.tsx file in each section's folder, and if something goes wrong, only that section will show an error while the rest of the page continues working.

2. Conditional Rendering

It's up to you what you do with the props sent to the layout.tsx file - you don't have to display them. Instead, you may want to show different sections based on conditions. For example, show an admin panel only if the user is an admin, or a log in screen if the user is not logged in:

export default function Layout({ admin, user }) {
  const isAdmin = checkIfUserIsAdmin();

  return isAdmin ? admin : user;
}

3. Creating Modals

You can also make pop-up windows that can be bookmarked and shared, and maintain their state when refreshed.

app/
├── layout.tsx
├── page.tsx
└── @auth/
    ├── default.tsx (Shows nothing)
    └── (.)login/
        └── page.tsx (Shows login modal)

The modal becomes a real route in your application while maintaining the user experience of a traditional modal.

Navigating with Parallel Routes

Things start to get a little more complicated when you start navigating beyond your initial page in to child pages of your content. By default, NextJS will look for a similar child page in your slot.

So, for example, if you had a page at dashboard/settings, NextJS would look for a @analytics/settings too instead of using the original component.

There are a couple of ways to resolve this - the first is by creating a default.tsx page to show a fallback. However, this starts to cause complications with your state when you are changing between server (when a user initially lands on your page) and client (when a user navigates to your page) side rendering.

A safer bet is to create a catch all folder using the same mechanic you'd use to create a NextJS slug - for example, [...catch]/page.tsx. This will catch any pages that do not exist and serve this page instead.

Why Parallel Routes Are Awesome

  • They make complex layouts simpler
  • Each section can have its own loading state and error handling
  • You can stream content as it becomes ready
  • Perfect for conditional content (like showing different things to logged-in users)
  • They work great with tabs, modals, and multi-section pages
  • Makes your code more organized by keeping related features together

Next time you need to build a dashboard or any page with multiple independent sections, give Parallel Routes a try! It's your new superpower for website routing!

Andi Smith

By Andi Smith

Andi Smith is a passionate technical leader who excels at building and scaling high-performing product engineering teams with a focus on business value. He has successfully helped businesses of all sizes from start up, scale up to enterprise build value-driven solutions.

Related Blog Posts