#nextjs #parallel-routes #slots #dashboard

Day 21 — Parallel Routes: Complex Layouts Made Easy

🧭 Day 21 — Parallel Routes: Complex Layouts Made Easy

Zero to Hero — Hands-on Next.js Tutorial

Traditionally, a layout has one “hole” for content: {children}. But what if you want a Dashboard that shows Analytics, Team, and Revenue simultaneously, but they all load independently and have their own loading states?

Enter Parallel Routes (Slots).


🟦 1. Naming Slots (@folder)

You define a slot by creating a folder starting with @. Examples: src/app/dashboard/@analytics and src/app/dashboard/@team.

These folders are not routes. You cannot visit /dashboard/@analytics. Instead, they are passed as props to the matching layout.


🟩 2. Consuming Slots

In src/app/dashboard/layout.tsx:

export default function DashboardLayout({
  children, // standard page.tsx
  analytics, // @analytics slot
  team,      // @team slot
}: {
  children: React.ReactNode
  analytics: React.ReactNode
  team: React.ReactNode
}) {
  return (
    <div className="dashboard-grid">
      <main>{children}</main>
      <aside>{analytics}</aside>
      <aside>{team}</aside>
    </div>
  );
}

Now, @analytics/page.tsx renders inside specific div. And @team/page.tsx renders in the other.


🟧 3. Independent Loading & Error

Here is the killer feature: Each slot can have its own loading.tsx and error.tsx.

If the “Revenue Chart” in @analytics is slow, only that box shows a spinner. The “Team” list loads instantly. If “Revenue” crashes, only that box shows an error. The rest of the dashboard stays alive.


🟥 4. default.tsx

If you navigate to a sub-page (e.g., /dashboard/settings), Next.js tries to render @analytics for that new URL. If @analytics doesn’t define a page for /settings, Next.js 404s.

To prevent this, create default.tsx in your slot. Next.js will use this as a fallback if the active URL doesn’t match the slot’s structure.


🧪 Challenge: Day 21

  1. Create /dashboard.
  2. Create /dashboard/@stats and /dashboard/@users.
  3. Add page.tsx to both. Make @stats delay for 3 seconds (await setTimeout). Add loading.tsx.
  4. Update dashboard/layout.tsx to render stats and users props side-by-side.
  5. Visit /dashboard and watch them load independently!

See you tomorrow for Authentication! 🔐