Skip to content
Watch the complete Next.js 15 course on YouTube

Parallel routes

This page explains how to implement parallel routes in Next.js to render multiple pages simultaneously within the same layout.

What are parallel routes?

Parallel routes is an advanced routing mechanism that allows you to render multiple pages simultaneously within the same layout. It is useful for building complex user interfaces that need to display multiple independent sections.

Creating parallel routes

Parallel routes use slots, created using the @folder naming convention. Each slot becomes a prop in the corresponding layout file. Consider a dashboard with three independent sections: analytics, revenue, and notifications:

  • Directoryapp/
    • Directorydashboard/
      • Directory@analytics/
        • page.tsx
      • Directory@revenue/
        • page.tsx
      • Directory@notifications/
        • page.tsx
      • layout.tsx
      • page.tsx

Create the slot components:

// app/dashboard/@analytics/page.tsx
export default function Analytics() {
return <div>Analytics content</div>;
}
// app/dashboard/@revenue/page.tsx
export default function Revenue() {
return <div>Revenue metrics</div>;
}
// app/dashboard/@notifications/page.tsx
export default function Notifications() {
return <div>Latest notifications</div>;
}

The layout receives each slot as a prop:

app/dashboard/layout.tsx
export default function DashboardLayout({
children,
analytics,
revenue,
notifications,
}: {
children: React.ReactNode;
analytics: React.ReactNode;
revenue: React.ReactNode;
notifications: React.ReactNode;
}) {
return (
<div>
<div>{children}</div>
<div style={{ display: "flex" }}>
<div>{analytics}</div>
<div>{revenue}</div>
<div>{notifications}</div>
</div>
</div>
);
}

Visit /dashboard to see the parallel routes in action. All three sections are rendered simultaneously.

Benefits of parallel routes

You might be wondering why you should use parallel routes when you can use a single layout file and render the sections in the same component. There are two main benefits:

Independent route handling

Parallel routes enable independent handling of each route. Each slot in your layout can manage its own loading and error states. This granular control is valuable when different sections load at varying speeds or encounter errors.

// app/dashboard/@analytics/loading.tsx
export default function AnalyticsLoading() {
return <div>Loading analytics...</div>;
}
// app/dashboard/@revenue/error.tsx
"use client";
export default function RevenueErrorBoundary({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<div>
<p>Error loading revenue metrics: {error.message}</p>
<button onClick={reset}>Retry</button>
</div>
);
}

For example, if the user analytics data is loading, you can display a loading spinner for that section while keeping other sections interactive. If revenue metrics fail to load, you can show an error message in that specific slot without affecting the rest of the dashboard.

Parallel routes support seamless sub-navigation within each route. Each slot functions as a mini-application with independent navigation and state management. Users can interact with each section separately — applying filters, sorting data, or navigating through pages — without affecting other sections.

For instance, the notifications section can switch between default and archived views. These interactions remain contained within the notifications section, and the URL updates accordingly. This makes the URL shareable and helps users track their location in the application.

Good to know

  • Slots are not route segments and don’t affect the URL structure
  • The children prop is an implicit slot - dashboard/page.tsx is equivalent to dashboard/@children/page.tsx
  • Each slot can have its own loading and error states
  • Slots enable independent navigation within each section
  • Common use cases include dashboards, split views, and admin interfaces