Wrap Pages With Shared Header, Sidebar, Providers
layout.tsx — Shared UI Across Segments
A layout wraps its segment and renders its children. Layouts persist across navigation, so state inside them stays alive.
What you'll learn
- Create the root `app/layout.tsx` with html and body
- Add nested layouts for inner segments
- Understand why layouts persist across navigation
A layout is a component that wraps everything in its segment. Layouts compose, persist across navigation, and are where you put headers, sidebars, and providers.
The Root Layout
Every Next.js app needs a root layout. It is the only place to render <html> and
<body>.
// app/layout.tsx
import './globals.css';
export const metadata = {
title: 'My App',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<header>Nav</header>
<main>{children}</main>
</body>
</html>
);
} The children prop is whatever route is being rendered.
Nested Layouts
Any segment can add its own layout.tsx. It wraps that segment’s children, in
addition to the root layout.
// app/dashboard/layout.tsx — wraps everything under /dashboard
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="dashboard-shell">
<nav>Dashboard Nav</nav>
{children}
</div>
);
} Now /dashboard/settings is wrapped by both the root layout and the dashboard layout.
Layouts Persist Across Navigation
When you navigate within a shared layout, that layout does not unmount. Any state inside it stays alive. This is the secret to fast, app-like transitions.
// app/dashboard/layout.tsx
'use client';
import { useState } from 'react';
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
// count survives navigation between /dashboard/* routes
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount((n) => n + 1)}>Clicked {count}</button>
{children}
</div>
);
} The next lesson covers how this all compares to the older Pages Router.
App Router vs Pages Router →