How to Use New Next.js 15 Parallel Routes for Building Dashboard Layouts With React 19
Next.js 15 introduced Parallel Routes, a powerful feature that lets you render multiple page slots in the same layout simultaneously, with independent navigation and state. When paired with React 19’s latest concurrent features and Server Components optimizations, building modular, high-performance dashboard layouts becomes faster and more intuitive than ever.
What Are Next.js 15 Parallel Routes?
Parallel Routes allow you to define multiple "slots" in a layout that map to different URL segments, each rendering their own page component. Unlike traditional nested routes, parallel routes load independently: navigating to a URL that updates one slot doesn’t trigger a full reload of other slots, preserving state and improving performance.
To define parallel routes, you use the @folder naming convention in your Next.js app directory. Each @folder represents a slot that can be targeted by URL segments, and the layout merges these slots into a single UI.
Key React 19 Features for Dashboard Layouts
React 19 brings several updates that complement Next.js 15 Parallel Routes for dashboard use cases:
- Server Components (RSC) Stability: React 19 cements RSC as a stable feature, letting you render dashboard data-heavy components on the server by default, reducing client-side bundle size.
- use() Hook: Read promises and context without
useEffect, simplifying data fetching in parallel route components. - Improved Concurrent Rendering: Better scheduling for parallel route updates, ensuring smooth transitions when multiple slots update at once.
Step-by-Step: Build a Dashboard Layout With Parallel Routes
Let’s build a sample dashboard with three parallel slots: a sidebar, main content area, and notifications panel. All slots will update independently based on URL changes.
1. Set Up the Next.js 15 Project
First, create a new Next.js 15 project with React 19 support:
npx create-next-app@latest dashboard-demo --typescript --tailwind --app
cd dashboard-demo
npm install react@19 react-dom@19 @types/react@19 @types/react-dom@19
Verify your package.json has Next.js 15+ and React 19 dependencies.
2. Define Parallel Route Slots
In your app directory, create the following structure to define parallel slots:
app/
├── layout.tsx
├── page.tsx
├── @sidebar/
│ └── page.tsx
├── @main/
│ └── page.tsx
└── @notifications/
└── page.tsx
The root layout.tsx will merge the three slots. Here’s the root layout code:
// app/layout.tsx
import type { ReactNode } from "react";
export default function RootLayout({
children,
sidebar,
main,
notifications,
}: {
children: ReactNode;
sidebar: ReactNode;
main: ReactNode;
notifications: ReactNode;
}) {
return (
{/* Sidebar slot */}
{sidebar}
{/* Main content slot */}
{main}
{/* Notifications slot */}
{notifications}
);
}
3. Add Content to Parallel Slots
Each @folder/page.tsx defines the content for that slot. Since we’re using React 19, we can use the use() hook to fetch data directly in Server Components (no need for getServerSideProps or client-side effects).
Example @sidebar/page.tsx (Server Component):
// app/@sidebar/page.tsx
import { use } from "react";
async function getNavLinks() {
const res = await fetch("https://api.example.com/nav-links", { cache: "force-cache" });
return res.json();
}
export default function Sidebar() {
const navLinks = use(getNavLinks());
return (
Dashboard
{navLinks.map((link: { id: string; label: string; href: string }) => (
{link.label}
))}
);
}
4. Handle Independent Navigation
Parallel routes support independent URL segments. For example, to update the main content slot without reloading the sidebar or notifications, you can use Next.js useRouter or components with the slot prop (new in Next.js 15).
Example link to update only the main slot:
import Link from "next/link";
export default function NavLink() {
return (
View Analytics
);
}
Navigating to this link will update the @main slot’s content to the /dashboard/analytics page, while the sidebar and notifications slots remain unchanged.
5. Add React 19 Client-Side Interactivity (Optional)
If you need client-side state for a slot (e.g., toggle notifications panel), mark the component as a Client Component with "use client" and use React 19’s use() hook for context or promises:
// app/@notifications/page.tsx
"use client";
import { use } from "react";
import NotificationsContext from "./notifications-context";
export default function NotificationsPanel() {
const notifications = use(NotificationsContext);
return (
Notifications
{notifications.map((n: { id: string; message: string }) => (
{n.message}
))}
);
}
Best Practices for Parallel Routes in Dashboards
- Keep Slots Focused: Each parallel slot should have a single responsibility (e.g., sidebar for nav, main for content) to avoid tight coupling.
- Use Server Components by Default: Leverage React 19’s stable RSC to render data-heavy slot content on the server, reducing client JS.
- Handle Fallback States: Use Next.js
loading.tsxin each@folderto show loading indicators for individual slots during navigation. - Avoid Over-Nesting: Parallel routes are for top-level layout sections; use nested routes for content within a slot.
Conclusion
Next.js 15 Parallel Routes combined with React 19’s performance and Server Component improvements make building modular, high-performance dashboards easier than ever. By splitting your layout into independent, navigable slots, you can create dashboards that feel fast, responsive, and easy to maintain. Try the sample code above to get started, and refer to the Next.js 15 and React 19 docs for advanced use cases.
Top comments (0)