layout file defines UI that is shared across multiple routes. Layouts persist across navigations and do not re-render when their child routes change.
app/dashboard/layout.js
Root layout
Theapp directory must include a root layout.js. The root layout defines the <html> and <body> tags and is applied to every route.
app/layout.js
Props
The nested layout or page rendered by this layout segment. May also include other special files like
loading.js or error.js when applicable.A promise that resolves to the dynamic route parameters from the root segment down to the current layout.
Use
app/dashboard/[team]/layout.js
| Route | URL | params |
|---|---|---|
app/dashboard/[team]/layout.js | /dashboard/1 | Promise<{ team: '1' }> |
app/shop/[tag]/[item]/layout.js | /shop/1/2 | Promise<{ tag: '1', item: '2' }> |
app/blog/[...slug]/layout.js | /blog/1/2 | Promise<{ slug: ['1', '2'] }> |
async/await or React’s use() to read the value.TypeScript helper
Use the globalLayoutProps helper to get strongly typed props, including params and named parallel route slots:
app/dashboard/layout.tsx
Types are generated during
next dev, next build, or next typegen. LayoutProps is globally available and does not need to be imported.Root layout requirements
- Must define
<html>and<body>tags - Must not add
<head>tags directly — use the Metadata API instead - Can have multiple root layouts using route groups (e.g.,
app/(shop)/layout.jsandapp/(marketing)/layout.js) - Navigating between different root layouts causes a full page load (not client-side navigation)
Caveats
Request object
Layouts do not have direct access to the incoming request. Use theheaders() and cookies() APIs from next/headers instead.
app/shop/layout.js
Query params
Layouts do not re-render on navigation, sosearchParams in a layout would become stale. To access current query params, use the searchParams prop in a page, or use useSearchParams() in a Client Component.
Pathname
Layouts do not re-render on navigation. To access the current pathname, useusePathname() in a Client Component.
Fetching data
Layouts cannot pass fetched data directly to child pages. However, you can fetch the same data in both the layout and the page. Next.js automatically deduplicatesfetch calls, so performance is not affected.
Examples
Exporting metadata
app/layout.js
Displaying content based on params
app/dashboard/[team]/layout.js
Reading params in a Client Component
Use React’suse() function to read the params promise in a Client Component:
app/page.js
Accessing child route segment
UseuseSelectedLayoutSegment() or useSelectedLayoutSegments() in a Client Component to read the active route segment below the layout:
app/ui/nav-link.js
Active nav links
app/ui/nav-links.js
Version history
| Version | Changes |
|---|---|
v15.0.0-RC | params is now a promise |
v13.0.0 | layout introduced |
