Suggest an editImprove this articleRefine the answer for “Layouts and templates in Next.js”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Layouts and templates in Next.js** wrap child pages and define shared UI. A layout persists across transitions (state survives), while a template remounts on every route change (state resets). ```tsx // layout.tsx - useState survives /a -> /b // template.tsx - remounts and resets on /a -> /b ``` **Key:** use layout by default; template only when you need a guaranteed remount per visit.Shown above the full answer for quick recall.Answer (EN)Image**Layouts and templates in Next.js** App Router are both wrapper components for child pages. The difference is one file name and a big behavioral gap: a layout stays mounted across page transitions, a template remounts every single time. ## Theory ### TL;DR - Layout = house walls (stay while rooms change); template = pop-up tent (rebuilt on every move) - Main difference: layouts preserve `useState` and skip re-renders; templates reset everything - Use layouts for navbars, sidebars, and auth providers (the default for 99% of cases) - Use templates only when you need a guaranteed remount per visit: animations, per-view logging, form resets - Root `layout.tsx` is required and must include `<html>` and `<body>` ### Quick example ```tsx // app/layout.tsx - state survives page transitions 'use client'; import { useState } from 'react'; export default function Layout({ children }: { children: React.ReactNode }) { const [count, setCount] = useState(0); return ( <div> <button onClick={() => setCount(c => c + 1)}>Count: {count}</button> {/* /a -> /b: count stays at whatever value it was */} {children} </div> ); } // app/template.tsx - remounts on every page transition export default function Template({ children }: { children: React.ReactNode }) { // /a -> /b: full remount, count resets to 0 return <div>{children}</div>; } ``` Switch from `/a` to `/b`: the layout keeps the counter value. The template resets to zero. ### Key difference Layouts render once per route segment and compose with `children` without remounting. React treats the layout as a stable node in the component tree, so `useState`, `useEffect`, and DOM nodes all survive client-side transitions. Templates get full teardown and remount on every route change. React's reconciler sees them as new instances each time, which re-triggers `useEffect` calls and resets all local state. ### When to use - Shared navbar or sidebar with state (open menus, active tab) → layout - Per-visit page view logging (`useEffect` needs to fire every time) → template - Enter/exit animations that depend on mount lifecycle → template - Nested segments with different context (`/dashboard` vs `/settings`) → nested layout - Auth provider wrapping the whole app → layout (session survives transitions) - Root `<html>`/`<body>` wrapper → layout (required by Next.js) ### Comparison table | Feature | Layout | Template | |---|---|---| | Remounts on transition | No | Yes, every time | | `useState` | Preserved | Reset | | `useEffect` | Does not rerun | Runs again | | DOM | Not recreated | Recreated | | Nesting | Composes up the tree | Supported, resets on each transition | | Typical use | Navbars, sidebars, providers | Animations, per-view logging | ### Nesting order inside a segment Next.js wraps special files in a fixed order within each segment: ``` layout.tsx template.tsx error.tsx (React Error Boundary) loading.tsx (React Suspense) not-found.tsx page.tsx ``` This order matters when you combine `template.tsx` and `loading.tsx` in the same segment. ### How it works internally Next.js scans the `app/` directory at build and dev time, treating `layout.tsx` and `template.tsx` as special RSC boundaries. On a route change, React's reconciler checks whether the layout component for the current segment is the same instance. It is, so no unmount happens. For templates, the reconciler sees a new instance on every transition and does a full VNode teardown and remount. Layouts stream to the browser first, painting the app shell; page content fills in after. ### Common mistakes **Auth state in a template:** ```tsx // app/template.tsx - WRONG 'use client'; const [user] = useSession(); // Resets on every transition, causes login loops ``` Templates remount on every route change, killing hook state. Session logic belongs in a layout. **Missing `{children}` in a layout:** ```tsx // app/docs/layout.tsx - WRONG export default function DocsLayout() { return <div>Docs header</div>; // Page content disappears } ``` Every layout must render `{children}`. Without it, child pages simply do not appear. **Template for the navbar.** The navbar will flicker and re-render on every link click. This is the most common App Router mistake I see in real codebases. Layouts exist precisely to prevent it. **Root layout without `<html>` and `<body>`:** ```tsx // app/layout.tsx - WRONG export default function RootLayout({ children }) { return <div>{children}</div>; // Hydration fails } ``` Next.js requires `<html>` and `<body>` in the root layout for SSR and streaming to work. ### Real-world usage - Vercel Dashboard: root + nested layouts keep sidebar and org-switcher state alive across transitions - Supabase + Next.js starters: layout wraps the auth provider so the session survives page changes - T3 Stack (tRPC/Next): nested layouts carry user and team context down the tree - Shadcn/ui templates: app shell in layout, rare onboarding screens in template - Any dashboard with tabs: layout holds `useState('analytics')` that persists from `/dashboard/analytics` to `/dashboard/reports` ### Follow-up questions **Q:** How do nested layouts compose? What does the tree look like for `app/blog/layout.tsx` and `app/blog/posts/layout.tsx`? **A:** Root layout wraps blog layout, which wraps posts layout. All three render once per load; only the innermost page component swaps on transition. No parent remounts. **Q:** Why use `template.tsx` instead of `loading.tsx` for custom reset UI? **A:** `loading.tsx` wraps the segment in a Suspense boundary and shows a spinner during data fetching. `template.tsx` handles full remount logic: state reset, animations, per-view effects. Different jobs. **Q:** When would you use a template for a dynamic product page? **A:** If you need fresh data on every visit without caching, a template inside a dynamic route (`/shop/[id]/template.tsx`) with `cache: 'no-store'` guarantees a refetch every time the user opens that product. **Q:** (Senior) How does layout streaming work with Suspense boundaries in children? **A:** The layout streams to the browser first as the HTML shell. Children with async fetches suspend independently. The browser paints the shell instantly; content fills in as each Suspense boundary resolves. No waterfall, because the layout does not block child streaming. ## Examples ### Basic: Root layout with shared header and footer ```tsx // app/layout.tsx export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> <Header /> <main>{children}</main> <Footer /> </body> </html> ); } // Header and Footer mount once; only <main> content swaps on page transitions ``` `Header` and `Footer` mount once for the lifetime of the app. Switching between any pages does not recreate them or reset their internal state. ### Intermediate: Dashboard with persistent sidebar state ```tsx // app/dashboard/layout.tsx 'use client'; import { useState } from 'react'; import Sidebar from '@/components/sidebar'; export default function DashboardLayout({ children, }: { children: React.ReactNode; }) { const [activeTab, setActiveTab] = useState('analytics'); // /dashboard/analytics -> /dashboard/reports: // activeTab stays 'analytics', Sidebar does not flicker return ( <div className="flex"> <Sidebar active={activeTab} onChange={setActiveTab} /> <main className="flex-1 p-8">{children}</main> </div> ); } ``` `activeTab` survives transitions because the layout never unmounts. The page content inside `<main>` swaps without touching the sidebar.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.