Layouts and Routing · Lesson 4 of 24
Next.js Layouts and Templates
A layout is UI shared by several pages – a header, a sidebar, a footer. Put a layout.tsx in a folder and it wraps every page in that folder and below. Layouts are one of the App Router's best features: when you navigate between pages that share a layout, the layout stays mounted – it doesn't re-render or lose its state – and only the page part changes.
In this lesson
- The root layout and nested layouts
- Layouts keep state across navigation – shown live
- Different layouts per section with route groups
template.tsx: a layout that remounts
Nested layouts
// app/layout.tsx
import Link from "next/link";
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<header>
<strong>LearnFrenzy</strong> <Link href="/">Home</Link> <Link href="/dashboard">Dashboard</Link>
</header>
{children}
<footer>© 2026 LearnFrenzy</footer>
</body>
</html>
);
}
// app/dashboard/layout.tsx
import Link from "next/link";
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div className="flex gap-6">
<aside>
<p>Dashboard menu</p>
<Link href="/dashboard">Overview</Link> <Link href="/dashboard/certificates">Certificates</Link>
</aside>
<section>{children}</section>
</div>
);
}
// app/dashboard/page.tsx
export default function Overview() {
return <h1>12 of 31 lessons complete</h1>;
}
// app/dashboard/certificates/page.tsx
export default function Certificates() {
return <h1>No certificates yet</h1>;
}
// app/page.tsx
export default function Home() {
return <h1>Welcome to LearnFrenzy</h1>;
}
URL: / LearnFrenzy Home Dashboard Welcome to LearnFrenzy © 2026 LearnFrenzy › click “Dashboard” URL: /dashboard LearnFrenzy Home Dashboard Dashboard menu Overview Certificates 12 of 31 lessons complete © 2026 LearnFrenzy › click “Certificates” URL: /dashboard/certificates LearnFrenzy Home Dashboard Dashboard menu Overview Certificates No certificates yet © 2026 LearnFrenzy
What wraps /dashboard/certificates
- app/layout.tsx – html, body, header, footer
- app/dashboard/layout.tsx – sidebar
- app/dashboard/certificates/page.tsx – the page
- app/dashboard/layout.tsx – sidebar
The root layout (app/layout.tsx) is required and must contain <html> and <body>. Every other layout is optional and just returns the UI around children.
Layouts keep their state
Here the dashboard layout contains an interactive note box (a Client Component). Type a note, then move between dashboard pages:
// app/dashboard/note-box.tsx
"use client";
import { useState } from "react";
export function NoteBox() {
const [note, setNote] = useState("");
return <input aria-label="Quick note" placeholder="Quick note" value={note} onChange={(e) => setNote(e.target.value)} />;
}
// app/dashboard/layout.tsx
import Link from "next/link";
import { NoteBox } from "./note-box";
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div>
<nav>
<Link href="/dashboard">Overview</Link> <Link href="/dashboard/certificates">Certificates</Link>
</nav>
<NoteBox />
{children}
</div>
);
}
// app/dashboard/page.tsx
export default function Overview() {
return <h1>Overview</h1>;
}
// app/dashboard/certificates/page.tsx
export default function Certificates() {
return <h1>Certificates</h1>;
}
Overview Certificates [Quick note…] Overview › type “Revise hooks” into Quick note Overview Certificates [Revise hooks] Overview › click “Certificates” Overview Certificates [Revise hooks] Certificates › click “Overview” Overview Certificates [Revise hooks] Overview
The note survives both navigations: the layout wasn't re-created, only the page inside it. That's what makes App Router navigation fast and keeps things like open menus, scroll positions in sidebars and media players intact.
template.tsx: remount on every navigation
Occasionally you want the opposite – fresh state for each page (an enter animation, a per-page feedback form, logging each view). A template.tsx works like a layout but gets a new instance on every navigation:
// app/dashboard/template.tsx
import { NoteBox } from "./note-box";
export default function DashboardTemplate({ children }: { children: React.ReactNode }) {
return (
<div>
<NoteBox />
{children}
</div>
);
}
// app/dashboard/layout.tsx
import Link from "next/link";
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div>
<nav>
<Link href="/dashboard">Overview</Link> <Link href="/dashboard/certificates">Certificates</Link>
</nav>
{children}
</div>
);
}
// app/dashboard/note-box.tsx
"use client";
import { useState } from "react";
export function NoteBox() {
const [note, setNote] = useState("");
return <input aria-label="Quick note" placeholder="Quick note" value={note} onChange={(e) => setNote(e.target.value)} />;
}
// app/dashboard/page.tsx
export default function Overview() {
return <h1>Overview</h1>;
}
// app/dashboard/certificates/page.tsx
export default function Certificates() {
return <h1>Certificates</h1>;
}
Overview Certificates [Quick note…] Overview › type “Revise hooks” into Quick note Overview Certificates [Revise hooks] Overview › click “Certificates” Overview Certificates [Quick note…] Certificates
This time the note is cleared when the page changes. Use layouts by default and templates only when you need the reset.
Different layouts for different sections
Route groups let sections have their own layouts without affecting URLs. A common structure:
app/
- layout.tsx – root: html, body, fonts, analytics
- (marketing)/layout.tsx – big header and footer
- page.tsx → /
- pricing/page.tsx → /pricing
- (app)/layout.tsx – sidebar, account menu
- dashboard/page.tsx → /dashboard
- settings/page.tsx → /settings
Layout rules worth remembering
- Layouts receive
children(andparamsin dynamic segments) but notsearchParams– they don't re-render on navigation, so they can't depend on the query string. - Put expensive, rarely-changing UI in layouts; it renders once and is reused.
- Next.js generates a global
LayoutProps<"/dashboard">type you can use for a layout's props.
Practice
Try it yourself
Add a
/settingssection whose layout shows "Settings" as a heading above every settings page, with a/settings/profilepage.Show solution
// app/settings/layout.tsx export default function SettingsLayout({ children }: { children: React.ReactNode }) { return ( <main> <h1>Settings</h1> {children} </main> ); }// app/settings/profile/page.tsx export default function Profile() { return <h2>Profile: Asha Verma</h2>; }Settings Profile: Asha Verma
Quick check
Does a layout re-render when you navigate between its child pages?
No – it stays mounted and keeps its state.
Which file is like a layout but remounts on navigation?
template.tsx.
Can a layout read searchParams?
No – only pages receive searchParams.
Summary
- layout.tsx wraps every page in its folder; layouts nest, and the root layout renders html and body.
- Layouts stay mounted across navigation, preserving state; templates remount.
- Route groups give sections different layouts without changing URLs.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.