Layouts

A layout.tsx wraps a segment and all pages beneath it, and it stays mounted across navigation.

Syntaxapp/layout.tsx exports a component receiving { children }

A layout is shared UI that wraps the pages in its segment. The root layout at app/layout.tsx is required and must render the <html> and <body> tags. Nested layouts wrap only their part of the tree.

Layouts nest and wrap child pages, preserving shared UI RootLayout (app/layout.tsx) — html, nav DashboardLayout (app/dashboard/layout.tsx) page.tsx (the current page) Only this inner part re-renders when you navigate between sibling pages. Outer layouts stay mounted (state preserved).
Each layout wraps the layouts and page beneath it, so shared chrome persists across navigation.

Layouts receive a children prop — the page or nested layout to render inside them. Crucially, layouts preserve state and do not re-render when you navigate between sibling pages.

Example

Example · typescript
// app/layout.tsx  (root layout — required)
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <nav>My Site</nav>
        {children}
      </body>
    </html>
  );
}

When to use it

  • A dashboard wraps all its pages in a sidebar layout defined once in app/dashboard/layout.tsx.
  • A root layout.tsx adds a global navigation bar and footer that remain mounted during client-side navigation.
  • An authenticated section adds a token check in its layout so every nested page is protected automatically.

More examples

Root layout with HTML shell

The root layout must include html and body tags and wraps every page in the app.

Example · ts
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <header>Site Nav</header>
        {children}
        <footer>Site Footer</footer>
      </body>
    </html>
  );
}

Nested segment layout

This layout applies only to routes under /dashboard and stays mounted when navigating between dashboard pages.

Example · ts
// app/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  return (
    <div style={{ display: 'flex' }}>
      <aside style={{ width: 200 }}>Sidebar</aside>
      <main style={{ flex: 1 }}>{children}</main>
    </div>
  );
}

Layout with async data

Layouts can be async Server Components, allowing them to fetch session data before rendering.

Example · ts
// app/dashboard/layout.tsx
import { getCurrentUser } from '@/lib/auth';

export default async function DashboardLayout({ children }: { children: React.ReactNode }) {
  const user = await getCurrentUser();
  return (
    <div>
      <p>Welcome, {user.name}</p>
      {children}
    </div>
  );
}

Discussion

  • Be the first to comment on this lesson.