0Pricing
Next.js 15 Fullstack (App Router + Server Actions) · Lezione

Route parallele con slot nominati e segmenti predefiniti

Esegua contemporaneamente più alberi di route indipendenti usando le convenzioni @slot e default.tsx.

Route parallele con slot nominati e segmenti predefiniti è una lezione Next.js 15 Fullstack (App Router + Server Actions) gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Next.js 15 Fullstack (App Router + Server Actions), e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Next.js 15 Fullstack (App Router + Server Actions) include 4 lezioni in totale.

Parti di questa lezione non sono ancora state tradotte e vengono mostrate in inglese.

What Are Parallel Routes?

Parallel Routes is a Next.js App Router feature that lets you render multiple independent route segments simultaneously inside a single layout. Each segment lives in its own named slot and can navigate, load, and error independently.

  • Think of a dashboard with a sidebar, a main panel, and a notification feed — all loaded in parallel, each with its own loading/error states.
  • Parallel routes are defined using the @folder naming convention inside a route segment directory.
  • Each slot becomes a prop on the parent layout.tsx.

This is fundamentally different from nested layouts: parallel slots share the same URL but render separate route trees side by side.

The @slot Convention

To create a parallel slot, prefix a folder with @ inside any route segment. Next.js treats these as named slots rather than URL segments.

  • app/dashboard/@analytics/page.tsx → slot named analytics
  • app/dashboard/@team/page.tsx → slot named team
  • The @folder name does not appear in the URL — visiting /dashboard renders all matching slots.

A typical parallel-routes directory tree looks like this:

// Directory layout (not runnable — filesystem structure)
// app/
//   dashboard/
//     layout.tsx          <- receives @analytics and @team as props
//     page.tsx            <- default slot content (children)
//     @analytics/
//       page.tsx
//       loading.tsx
//     @team/
//       page.tsx
//       error.tsx

Writing the Parallel Layout

The parent layout.tsx receives each named slot as a React prop alongside the standard children prop. You can position them anywhere in the JSX.

  • TypeScript types for slots are just React.ReactNode.
  • Slots are completely independent — one can suspend while another is already rendered.
  • The children prop itself is an implicit slot named children.
// app/dashboard/layout.tsx
import React from 'react';

interface DashboardLayoutProps {
  children: React.ReactNode;
  analytics: React.ReactNode;
  team: React.ReactNode;
}

export default function DashboardLayout({
  children,
  analytics,
  team,
}: DashboardLayoutProps) {
  return (
    <div className="dashboard-grid">
      <main className="col-span-2">{children}</main>
      <aside className="analytics-panel">{analytics}</aside>
      <aside className="team-panel">{team}</aside>
    </div>
  );
}

Creating Slot Pages

Each named slot needs its own page.tsx. These pages are standard Server Components (or Client Components) — there is nothing special about their internal structure.

  • Slots can have their own loading.tsx, error.tsx, and nested routes.
  • Data fetching inside a slot is independent: one slot can await a slow database call without blocking the others.
// app/dashboard/@analytics/page.tsx
import { getAnalyticsSummary } from '@/lib/analytics';

export default async function AnalyticsSlot() {
  const summary = await getAnalyticsSummary();

  return (
    <section>
      <h2 className="text-lg font-semibold">Analytics</h2>
      <p>Total visits: <strong>{summary.totalVisits}</strong></p>
      <p>Conversion rate: <strong>{summary.conversionRate}%</strong></p>
    </section>
  );
}

// app/dashboard/@team/page.tsx
import { getTeamMembers } from '@/lib/team';

export default async function TeamSlot() {
  const members = await getTeamMembers();

  return (
    <ul>
      {members.map((m) => (
        <li key={m.id}>{m.name} — {m.role}</li>
      ))}
    </ul>
  );
}

Independent Loading States

Each slot can ship its own loading.tsx. Next.js wraps it in a Suspense boundary automatically, so slots stream in independently — fast slots appear immediately while slow ones show a skeleton.

  • This eliminates the waterfall problem common in single-tree layouts.
  • Users see meaningful UI much sooner because partial content renders first.
// app/dashboard/@analytics/loading.tsx
export default function AnalyticsLoading() {
  return (
    <div className="animate-pulse space-y-2">
      <div className="h-4 bg-gray-200 rounded w-1/2" />
      <div className="h-4 bg-gray-200 rounded w-3/4" />
      <div className="h-4 bg-gray-200 rounded w-2/3" />
    </div>
  );
}

// app/dashboard/@team/loading.tsx
export default function TeamLoading() {
  return (
    <ul className="space-y-2">
      {Array.from({ length: 4 }).map((_, i) => (
        <li key={i} className="h-4 bg-gray-200 rounded animate-pulse" />
      ))}
    </ul>
  );
}

The Problem: Soft Navigation and Missing Slots

Parallel routes shine during hard navigation (full page load), but soft navigation (client-side link clicks) reveals a problem.

When a user navigates to a sub-route — for example /dashboard/settings — Next.js looks for a matching page in every active slot. If a slot has no page for /settings, it becomes unmatched.

  • An unmatched slot does not simply disappear — Next.js needs to know what to render.
  • Without a fallback, Next.js renders a 404 for the entire page.
  • The solution is default.tsx.

Rescuing Unmatched Slots with default.tsx

default.tsx is the fallback file Next.js renders for a slot when it has no matching page.tsx for the current URL. It acts like a catch-all within the slot's subtree.

  • Place default.tsx at the root of each slot: @analytics/default.tsx.
  • During soft navigation to an unmatched sub-route, Next.js renders default.tsx instead of 404-ing.
  • default.tsx receives the same params as a page; you can use it to show the slot's normal content unchanged, or a meaningful placeholder.
// app/dashboard/@analytics/default.tsx
// Rendered when the current URL has no matching page in this slot.
import { getAnalyticsSummary } from '@/lib/analytics';

export default async function AnalyticsDefault() {
  // Reuse the same data as the main analytics page so the slot
  // stays visible during navigation to other sub-routes.
  const summary = await getAnalyticsSummary();

  return (
    <section>
      <h2 className="text-lg font-semibold">Analytics</h2>
      <p>Total visits: <strong>{summary.totalVisits}</strong></p>
    </section>
  );
}

default.tsx for the Root children Slot

The implicit children slot (i.e. page.tsx at the segment root) also needs a default.tsx when parallel slots are present. Without it, navigating to a named slot's sub-route that doesn't match children will 404.

  • Add app/dashboard/default.tsx alongside app/dashboard/page.tsx.
  • It typically re-renders the same content as page.tsx, or a neutral empty state.
// app/dashboard/default.tsx
// Fallback for the implicit 'children' slot during soft navigation.
export default function DashboardDefault() {
  return (
    <div>
      <h1 className="text-2xl font-bold">Dashboard</h1>
      <p className="text-gray-500">Select an item to get started.</p>
    </div>
  );
}

Nested Routes Inside Slots

Named slots support their own nested route hierarchies. You can add [id] dynamic segments, route groups, or additional layouts entirely inside a slot — all without affecting the URL segments of sibling slots.

  • Example: @analytics/chart/[chartId]/page.tsx renders at /dashboard/chart/42 only inside the analytics slot.
  • The parent layout and other slots remain untouched.
  • Each nested level inside a slot can have its own loading.tsx, error.tsx, and default.tsx.
// app/dashboard/@analytics/chart/[chartId]/page.tsx
interface Props {
  params: Promise<{ chartId: string }>;
}

export default async function ChartDetailPage({ params }: Props) {
  const { chartId } = await params;

  // In a real app, fetch chart data here
  return (
    <div>
      <h3>Chart #{chartId}</h3>
      <p>Detailed breakdown for chart {chartId}.</p>
    </div>
  );
}

// app/dashboard/@analytics/chart/[chartId]/default.tsx
export default function ChartDefault() {
  return <p className="text-sm text-gray-400">No chart selected.</p>;
}

Practical Pattern: Modal Alongside Page

A classic use-case for parallel routes is rendering a modal in one slot while the main content stays visible in another — without losing the current scroll position or unmounting components.

  • Create an @modal slot with a default.tsx that returns null (nothing visible by default).
  • When a user clicks a trigger, Next.js navigates to the modal's page, filling the slot.
  • The main children slot continues rendering unchanged.
// app/dashboard/@modal/default.tsx
// Renders nothing when no modal route is matched.
export default function ModalDefault() {
  return null;
}

// app/dashboard/@modal/user/[id]/page.tsx
interface Props {
  params: Promise<{ id: string }>;
}

export default async function UserModal({ params }: Props) {
  const { id } = await params;
  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center">
      <div className="bg-white rounded-lg p-6 w-96">
        <h2 className="text-xl font-bold">User #{id}</h2>
        <p>Profile details would appear here.</p>
      </div>
    </div>
  );
}

TypeScript Tip: Strongly-Typed Slot Props

As the number of slots grows, keep your layout props explicit with a dedicated TypeScript interface. This makes refactoring safer and IDE autocompletion more helpful.

  • Slot props are always React.ReactNode — they accept any renderable value Next.js injects.
  • You can combine parallel slots with searchParams or route params in the same layout signature.
  • For shared slot configuration (e.g. theming), pass context via a React Context Provider inside the layout rather than prop-drilling through each slot page.
// app/dashboard/layout.tsx — full typed version
import React from 'react';
import { DashboardNav } from '@/components/DashboardNav';

interface DashboardLayoutProps {
  children: React.ReactNode;   // implicit slot
  analytics: React.ReactNode;  // @analytics slot
  team: React.ReactNode;       // @team slot
  modal: React.ReactNode;      // @modal slot
  params: Promise<{ orgId: string }>;
}

export default async function DashboardLayout({
  children,
  analytics,
  team,
  modal,
  params,
}: DashboardLayoutProps) {
  const { orgId } = await params;

  return (
    <>
      <DashboardNav orgId={orgId} />
      <div className="grid grid-cols-3 gap-4 p-4">
        <div className="col-span-2">{children}</div>
        <div className="space-y-4">
          {analytics}
          {team}
        </div>
      </div>
      {modal}
    </>
  );
}

Knowledge Check: When Is default.tsx Required?

Test your understanding of the default.tsx file in parallel routes.

Recap: Parallel Routes with Named Slots and Default Segments

Here is what you learned in this lesson:

  • Parallel Routes let you render multiple independent route trees in the same layout simultaneously, each in its own @slot folder.
  • Named slots use the @folderName convention and become props (React.ReactNode) on the parent layout.tsx.
  • Each slot is truly independent: it can have its own loading.tsx, error.tsx, nested routes, and data fetching without blocking siblings.
  • default.tsx is the critical fallback file. Without it, soft navigation to a URL that does not match a slot produces a 404. Place a default.tsx in every slot — including the implicit children slot — to prevent this.
  • Common patterns include dashboard multi-panels (analytics + team side by side) and modal-alongside-page where the @modal slot's default.tsx returns null.
  • Keep layout props strongly typed with a TypeScript interface as the slot count grows.

With parallel routes and default.tsx in place, your layouts become resilient, independently streaming, and far easier to reason about than a single monolithic route tree.

Domande Frequenti

La lezione «Route parallele con slot nominati e segmenti predefiniti» è gratuita?

Sì — il testo completo di «Route parallele con slot nominati e segmenti predefiniti» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Next.js 15 Fullstack (App Router + Server Actions), passa a CoddyKit PRO. Il corso Next.js 15 Fullstack (App Router + Server Actions) include 4 lezioni in totale.

Cosa imparerò in «Route parallele con slot nominati e segmenti predefiniti»?

Esegua contemporaneamente più alberi di route indipendenti usando le convenzioni @slot e default.tsx. Eserciti Next.js 15 Fullstack (App Router + Server Actions) con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Next.js 15 Fullstack (App Router + Server Actions)?

Non è richiesta alcuna esperienza precedente. Next.js 15 Fullstack (App Router + Server Actions) su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Route parallele con slot nominati e segmenti predefiniti»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Next.js 15 Fullstack (App Router + Server Actions)?

Sì. Ogni lezione Next.js 15 Fullstack (App Router + Server Actions) include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Route parallele con slot nominati e segmenti predefiniti
  2. Route intercettanti per esperienze modali condivise
  3. Rendering condizionale degli slot per dashboard e tab
  4. Creazione di un flusso foto-modale con navigazione morbida
← Torna a Next.js 15 Fullstack (App Router + Server Actions)