Skip to content

Next.js Layouts

Layouts render shared UI — like navigation bars, sidebars, and footers — that wraps a page and persists across navigation between routes that share it. This lesson covers the root layout, nested layouts, and how they render children.

The Root Layout Is Required

Every App Router project needs exactly one root layout.tsx, directly inside app/. It is the only file responsible for rendering <html> and <body> tags, and every other route in the project renders inside it. Without a root layout, Next.js will refuse to build.

Nested layouts (any layout.tsx inside a subfolder) do not render <html>/<body> again — they simply wrap the routes beneath them with additional, more specific shared UI, nesting inside the root layout and any layouts between them.

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

{children} is where Next.js renders whichever nested layout or page matches the current route.

Layout Component Signature

export default function Layout({
  children,
}: {
  children: React.ReactNode;
}) {
  return <section>{children}</section>;
}
  • A layout must accept and render its children prop — otherwise, nothing beneath it renders.
  • Layouts do not receive searchParams, only params for any dynamic segments in their own path.
  • Nested layouts wrap children with additional UI on top of whatever the parent layout already renders.
  • Only the root layout should render <html> and <body>.

Layouts Cheat Sheet

Rules every layout in the App Router follows.

Rule Detail
Root layout location app/layout.tsx (required)
Root layout responsibility Renders <html> and <body>
Nested layout location Any layout.tsx inside a subfolder
Required prop children: React.ReactNode
Persists across navigation? Yes, for routes that share it
Receives searchParams? No

A Realistic Shared Navigation Layout

A common real-world use of a nested layout is a persistent sidebar for a dashboard section, shared by every route beneath /dashboard without duplicating the sidebar markup in every page.

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

Every route under /dashboard (settings, profile, billing, etc.) automatically renders inside this sidebar layout.

Layouts Can Export Metadata Too

Like pages, layouts can export a metadata object. Metadata from nested layouts and pages merges together, with more specific (deeper) values overriding more general ones, which is covered fully in the Metadata API lesson.

  • A root layout might set a default title.template used across the whole site.
  • A page's own metadata export can override just the title, while inheriting everything else.

Common Mistakes

  • Forgetting to render {children} inside a custom layout, which silently blanks out every nested route.
  • Adding <html>/<body> tags to a nested layout, duplicating what the root layout already provides.
  • Expecting a layout to receive searchParams the way a page does.
  • Making an entire layout a Client Component just because one small piece of UI inside it needs interactivity.

Key Takeaways

  • Every App Router project requires exactly one root layout.tsx rendering <html> and <body>.
  • Nested layouts wrap deeper routes with additional shared UI, nesting inside parent layouts.
  • A layout must render its children prop for anything beneath it to appear.
  • Layouts persist across navigation between routes that share them, unlike pages.
  • Layouts can export metadata, which merges with metadata from nested pages.

Pro Tip

Keep layouts as Server Components whenever possible, and extract only the interactive piece (like a mobile menu toggle button) into its own small Client Component rendered inside the layout — this keeps navigation-heavy shared UI fast and avoids shipping unnecessary JavaScript.