Layouts & Templates
What is a layout?
A layout is UI that is shared by several pages — header, footer, sidebar. You write it once in layout.jsx, and it receives the current page as the children prop.
The root layout (required)
// app/layout.jsx — wraps every page of the site
import Header from '@/components/Header'
import Footer from '@/components/Footer'
import './globals.css'
export const metadata = {
title: { default: 'EduSite – Learn coding in Hindi + English', template: '%s | EduSite' },
description: 'Coaching institute website built with Next.js.',
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<Header />
<main>{children}</main> {/* the current page goes here */}
<Footer />
</body>
</html>
)
}- It must render
<html>and<body>. - It is a Server Component; import small Client Components (like an interactive Header) into it.
metadatahere becomes the default for all pages;template: '%s | EduSite'adds your brand to every page title.
Nested layouts
Add layout.jsx inside a folder to wrap only that section:
// app/dashboard/layout.jsx — only for /dashboard/* pages
import Link from 'next/link'
export default function DashboardLayout({ children }) {
return (
<div style={{ display: 'grid', gridTemplateColumns: '220px 1fr', gap: 20 }}>
<aside>
<h3>Student panel</h3>
<nav style={{ display: 'grid', gap: 8 }}>
<Link href="/dashboard">Overview</Link>
<Link href="/dashboard/results">Results</Link>
<Link href="/dashboard/fees">Fees</Link>
</nav>
</aside>
<section>{children}</section>
</div>
)
}
// app/dashboard/page.jsx → /dashboard
// app/dashboard/results/page.jsx → /dashboard/results (same sidebar)📁 app/ layout.jsx # Root layout: Header + Footer (every page) page.jsx # / 📁 dashboard/ layout.jsx # Sidebar (only /dashboard/*) page.jsx # /dashboard 📁 results/ page.jsx # /dashboard/results 📁 fees/ page.jsx # /dashboard/fees
How layouts wrap pages
Layouts keep their state
When you move from /dashboard to /dashboard/fees, Next.js does not re-render the layout — only the page swaps. A search box in the sidebar keeps its text, and the scroll position of the sidebar stays. This makes navigation feel instant.
template.jsx — when you want a fresh start
// app/blog/template.jsx — a NEW instance on every navigation
export default function BlogTemplate({ children }) {
return <div className="fade-in">{children}</div>
}
// Useful for: enter animations, resetting a form, logging each page view.layout.jsx
- Stays mounted between pages
- Keeps state and scroll
- Use for header, sidebar
template.jsx
- Re-created on each navigation
- State resets
- Use for animations, per-page effects
Default metadata in layouts
Pages override what they need. With the root layout above, export const metadata = { title: 'All Courses' } in app/courses/page.jsx produces the title "All Courses | EduSite". You will master this in the Metadata & SEO lesson.
Common mistakes
- Adding
<html>/<body>again in a nested layout → invalid HTML. Only the root layout has them. - Forgetting to render
{children}→ pages disappear. - Putting
'use client'on the root layout just for a menu → the whole site becomes client-side. Make only the Header a Client Component. - Expecting the layout to re-fetch data on every page change → it does not; fetch per-page data in the page.
Summary
layout.jsx= shared UI; it wrapschildren.- The root layout is required and owns
<html>/<body>. - Nested layouts wrap one section; layouts persist across navigation.
- Use
template.jsxwhen each visit needs a fresh instance.
Build /dashboard, /dashboard/results and /dashboard/fees with a shared sidebar layout. Add a text input to the sidebar and check that its text stays when you switch pages.
