Next.js Layouts
A layout is a shared UI wrapper that stays consistent across multiple pages. Navigation bars, footers, and sidebars are classic examples of layout content. Instead of adding these elements to every page file, you define them once in a layout and every page inside that folder automatically inherits it.
The Root Layout
Every Next.js app must have a root layout at app/layout.js. This file wraps every single page in your entire application. It is required and cannot be removed.
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<header>My Website Header</header>
<main>{children}</main>
<footer>My Website Footer</footer>
</body>
</html>
);
}
The children prop is where the current page gets inserted. Every page you visit replaces children while the header and footer stay in place.
Diagram: How the Layout Wraps Pages
LAYOUT.JS (stays fixed):
┌──────────────────────────┐
│ Header (always visible) │
│ ┌────────────────────┐ │
│ │ {children} │ │
│ │ ← Page content │ │
│ │ goes here │ │
│ └────────────────────┘ │
│ Footer (always visible) │
└──────────────────────────┘
USER VISITS /about → children = About page content
USER VISITS /blog → children = Blog page content
Nested Layouts
You can add a layout.js file inside any subfolder. This layout applies only to pages inside that folder. It wraps around the page but sits inside the root layout.
app/
layout.js ← Root layout
dashboard/
layout.js ← Dashboard layout (for /dashboard/* only)
page.js
analytics/
page.js
settings/
page.js
Nested Layout Stacking
VISITING /dashboard/analytics:
Root Layout
└── Dashboard Layout (adds sidebar)
└── Analytics Page (actual content)
What the user sees:
┌───────────────────────────────┐
│ Site Header (root layout) │
│ ┌─────────┬─────────────┐ │
│ │Sidebar │ Analytics │ │
│ │(dash │ Page │ │
│ │layout) │ (content) │ │
│ └─────────┴─────────────┘ │
│ Site Footer (root layout) │
└───────────────────────────────┘
Creating a Dashboard Layout
// app/dashboard/layout.js
export default function DashboardLayout({ children }) {
return (
<div className="dashboard-wrapper">
<aside>
<nav>
<a href="/dashboard">Overview</a>
<a href="/dashboard/analytics">Analytics</a>
<a href="/dashboard/settings">Settings</a>
</nav>
</aside>
<section>{children}</section>
</div>
);
}
Layouts Preserve State
When a user navigates between pages that share a layout, the layout does not re-render. Only the page content changes. This means any state inside the layout — like an open dropdown or a search input value — stays intact during navigation.
User on /dashboard → Types in search bar → Navigates to /dashboard/analytics
↓
Search bar keeps its value (layout preserved)
Only the main content area changes
Adding Metadata in Layouts
You can export a metadata object from a layout to set default SEO properties for all pages inside that layout. Individual pages can override these defaults.
// app/layout.js
export const metadata = {
title: 'My Website',
description: 'Welcome to my awesome website',
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Template Files
Next.js also provides a template.js file that works like a layout but re-renders every time you navigate to a page. Use this when you need fresh state on each visit — like a page animation that should replay on every navigation.
layout.js → Persists across navigation (state preserved) template.js → Re-renders on every navigation (fresh state)
Key Takeaway
Layouts wrap pages with shared UI like headers, footers, and sidebars. The root layout at app/layout.js is required and wraps every page. Nested layouts apply to specific sections of your app. Layouts persist across page navigations, so their internal state does not reset when users move between pages.
