Topic 11 of 47
Layouts & Templates
Overview
Layouts are shared UI that wraps multiple pages. They persist across navigation — great for navbars, sidebars, and auth shells. Templates are similar but remount on every navigation, useful for animations.
Syntax
tsx
// app/layout.tsx — root layout (required)
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Navbar />
<main>{children}</main>
<Footer />
</body>
</html>
);
}
// app/dashboard/layout.tsx — nested layout
export default function DashboardLayout({ children }) {
return (
<div className="dashboard">
<Sidebar />
<div className="content">{children}</div>
</div>
);
}
// app/dashboard/page.tsx — renders inside both layouts
// URL: /dashboard
export default function DashboardPage() {
return <h1>Dashboard</h1>;
}Common Pitfalls
- Layouts don't re-render on navigation between child pages — they persist. This means layout state is shared across all child routes.
- Root layout (app/layout.tsx) is required and must include <html> and <body> tags.
- Interview tip: For per-page animated transitions, use template.tsx instead of layout.tsx — templates remount on every navigation.
Real-World Example
Dashboard layout with sidebar and breadcrumbs
example
tsx
// app/(dashboard)/layout.tsx
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
export default async function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
const session = await auth();
if (!session) redirect("/login"); // server-side auth check!
return (
<div className="flex h-screen">
<Sidebar user={session.user} />
<div className="flex-1 overflow-auto">
<TopBar user={session.user} />
<main className="p-6">{children}</main>
</div>
</div>
);
}