← Back to chapters
03beginner

Layouts, Templates & Metadata

Shared UI across pages, nested layouts, route groups, and SEO metadata.

Layouts: Shared UI That Persists

A layout wraps your pages. Think navbar, sidebar, footer. Stuff that stays the same across multiple pages. The beautiful thing? Layouts DON'T re-render when you navigate between their child pages. They persist state.

Root Layout

Every Next.js app needs a root layout. This is the top-level wrapper for your entire app:

src/app/layout.tsx
tsx
1// src/app/layout.tsx
2import type { Metadata } from "next";
3
4export const metadata: Metadata = {
5title: "My App",
6description: "Built with Next.js",
7};
8
9export default function RootLayout({
10children,
11}: {
12children: React.ReactNode;
13}) {
14return (
15 <html lang="en">
16 <body>
17 <nav>My Navbar</nav>
18 {children}
19 <footer>My Footer</footer>
20 </body>
21 </html>
22);
23}
⚠️

Important

The root layout MUST contain and tags. It's the only layout that requires them. Nested layouts just return regular JSX.

Nested Layouts

Here's where it gets powerful. You can have layouts at ANY level. An admin section can have its own sidebar layout:

src/app/admin/layout.tsx
tsx
1// src/app/admin/layout.tsx
2export default function AdminLayout({
3children,
4}: {
5children: React.ReactNode;
6}) {
7return (
8 <div className="flex">
9 <aside className="w-64 bg-gray-900 text-white min-h-screen p-4">
10 <nav>
11 <a href="/admin">Dashboard</a>
12 <a href="/admin/users">Users</a>
13 <a href="/admin/settings">Settings</a>
14 </nav>
15 </aside>
16 <main className="flex-1 p-8">{children}</main>
17 </div>
18);
19}

Now every page under '/admin/*' automatically gets this sidebar. Navigate between admin pages and the sidebar stays. No re-mount, no flash.

Route Groups: Organization Without URLs

Sometimes you want to organize routes without affecting the URL. Wrap folder names in parentheses:

Route groups with (parentheses)
text
1src/app/
2├── (marketing)/
3│ ├── layout.tsx ← Marketing-specific layout
4│ ├── about/page.tsx → /about
5│ └── pricing/page.tsx → /pricing
6├── (dashboard)/
7│ ├── layout.tsx ← Dashboard-specific layout
8│ ├── settings/page.tsx → /settings
9│ └── profile/page.tsx → /profile
10└── layout.tsx ← Root layout
🚀

When I use route groups

I use them when different sections of my app need different layouts but I don't want the group name in the URL.
• Marketing pages get a landing-page layout
• Dashboard pages get an app layout
• Same URL structure, different wrapping UI

Metadata & SEO

Next.js handles your tags. Export a 'metadata' object from any page or layout:

src/app/blog/page.tsx
tsx
1// src/app/blog/page.tsx
2import type { Metadata } from "next";
3
4export const metadata: Metadata = {
5title: "Blog | My Site",
6description: "Read my latest articles about web development.",
7openGraph: {
8 title: "Blog | My Site",
9 description: "Read my latest articles",
10 images: ["/og-blog.png"],
11},
12};
13
14export default function BlogPage() {
15return <h1>Blog</h1>;
16}

Child metadata merges with and overrides parent metadata. So your blog page gets the site-wide defaults PLUS its own title and description. No more manually managing components.

Watch and Learn