skip to content

Layouts, Templates, and Nesting

Layouts persist across navigation while templates remount, and that single difference decides whether scroll position, form state, and animations survive a route change. Interviewers use it to check you understand what actually re-renders.

part ofNext.jsoverview, primer and where to startread it →
on this pageshow

explore

questions

4

In the Next.js App Router, what is special about the root layout at app/layout.tsx compared with a nested layout further down the tree?

level: juniorimportance: must knowfreq 68%

answer

  1. outermost wrapper of every route
  2. it is the document itself
  3. two tags only this file renders
  4. head is generated, not hand-written
  5. cost is paid on every route

basics

~20 s

The root layout is required, wraps every route in the app, and is the only layout that renders the <html> and <body> tags. Nested layouts render plain markup inside it and apply only to their own segment and below.

solid answer

~50 s

`app/layout.tsx` is the top of the App Router tree, so every route renders inside it and it never unmounts while the user stays in the app. It is also the only layout that must return the document shell — the `<html>` and `<body>` elements — because Next renders the whole page from this component rather than from a separate document template. A nested layout returns ordinary markup and wraps only the segment it lives in plus everything below. Both take a `children` prop; only the root one is mandatory. You do not hand-write a `<head>` element in it — you export `metadata` or `generateMetadata` from the segment and Next builds the head for you. Practically it is where global fonts, providers, and app-wide chrome go, and anything you put there is paid for on every single route.

code

tsx · 14 lines
tsx
import type { ReactNode } from 'react';

export const metadata = {
  title: 'Acme',
  description: 'Store front',
};

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

go deeper

for a junior

Recall that app/layout.tsx is required, wraps every route, and is the one file that returns the <html> and <body> tags with children inside the body.

for a middle

Explain why head tags come from the metadata exports rather than a hand-written <head>, which props a layout actually receives, and why nested layouts return plain markup instead of a document shell.

for a senior

Treat it as a budget: everything in the root layout ships on every route. Be ready to argue what earns a place there, why marking it a client entry point is a costly mistake, and how you would move section-specific chrome down into nested layouts.

for a principal

Own the app-wide shell as a shared resource. Set the rule for which providers and global assets may live at the root, keep the critical path of every page small, and make sure sections cannot quietly grow their dependencies into it.

## Where the root layout sits The App Router builds a page by composing layouts from the top of the `app/` directory down to the matched segment. `app/layout.tsx` is the outermost of those, so it wraps every route in the application, including error and not-found UI. Being outermost has a consequence that trips people up: it is never unmounted during client navigation, because there is no navigation that leaves it. Whatever state, subscription or provider you mount there lives for the whole session. ## The document shell In the App Router the rendered HTML document comes from your own component tree, not from a separate template file. That is why the root layout carries the requirement no nested layout has: it must render `<html>` and `<body>`. ```tsx // app/layout.tsx import type { ReactNode } from 'react'; export const metadata = { title: 'Acme' }; export default function RootLayout({ children }: { children: ReactNode }) { return ( <html lang="en"> <body>{children}</body> </html> ); } ``` A nested layout — `app/dashboard/layout.tsx` — returns a `<div>` or a fragment. If it rendered `<html>` you would get nested document elements, which is invalid HTML. The rule is easy to remember precisely because it applies to exactly one file. ## No hand-written head Because the document comes from your components, the instinct is to add a `<head>` with `<title>` and meta tags. Don't. The App Router owns the head through the metadata exports: a static `metadata` object or an async `generateMetadata` function exported from any layout or page. Next collects those down the segment tree and emits the tags. Hand-writing head elements bypasses that system and produces duplicates or tags Next later overwrites. One consequence worth knowing: metadata exports are only supported in Server Components. Since the root layout is a Server Component by default, keep it that way — adding `'use client'` at the top of the file both disables its metadata export and pulls the whole application into the client module graph. Interactive pieces belong in child components that opt into the client themselves. ## What the root layout receives A layout gets a `children` prop and, when its segment is dynamic, a `params` prop. It does **not** receive `searchParams` — only pages do. That is not an oversight: layouts are preserved across navigation and are not re-rendered when only the query string changes, so a query value handed to them could be stale by construction. If shared chrome needs the query, read it in a Client Component nested inside the layout. In Next.js 15 and later `params` is a Promise, so you `await` it in an async layout; in earlier versions it was a plain object. ## What belongs there Everything in the root layout is loaded on every route, so it deserves a stricter budget than any other file: - **Belongs:** the `<html lang>` attribute, global stylesheet import, fonts loaded through `next/font`, context providers the entire app needs, site-wide header or footer, default `metadata`. - **Does not belong:** anything only one section needs — that goes in that section's nested layout — and heavy client-side widgets, which drag their whole dependency tree into the initial payload of every page. ## How this reads in an interview The expected answer has three parts, and candidates usually give one. Say (1) it is required and wraps every route, (2) it is the only layout rendering `<html>` and `<body>`, and (3) head tags come from the metadata exports rather than a hand-written `<head>`. Adding the cost argument — everything here is on the critical path of every page — is what turns a recited rule into a demonstration that you have shipped with it.

  • Does a layout receive searchParams the way a page does?
    No. Layouts receive `children` and, for a dynamic segment, `params`; `searchParams` is a page-only prop. Layouts are preserved across navigation and are not re-rendered when only the query string changes, so a query value passed to them could not be kept correct. Read the query in a Client Component nested inside the layout instead. Note that in Next.js 15 and later `params` is a Promise you await.
  • Can you put 'use client' at the top of the root layout?
    Avoid it. Metadata exports are only supported in Server Components, so the file's `metadata` or `generateMetadata` would stop working, and marking the outermost component as a client entry point pulls the entire application into the client module graph. Keep the root layout a Server Component and move interactivity into nested components that declare `'use client'` themselves.
  • How do you add a title and meta description if you should not write a <head> element?
    Export a `metadata` object, or an async `generateMetadata` function when the values depend on data, from the layout or page. Next collects those exports down the segment tree and renders the head tags itself. Hand-written head elements bypass that and end up duplicated or overwritten.

saying these in an interview costs you the question

  • Every layout must render <html> and <body>
  • Add a <head> block with your title tags there
  • The root layout re-mounts on each navigation
  • Layouts get searchParams just like pages do
  • Put all providers there so nothing is duplicated

context

open as a page

In the Next.js App Router, what is the difference between a segment's layout.tsx and its template.tsx, and how does that difference show up when the user navigates between two pages under that segment?

level: middleimportance: must knowfreq 78%

basics

~20 s

A layout persists across navigation: its instance stays mounted, state and effects survive, only the child page swaps. A template wraps children the same way but is remounted on every navigation, so state resets, effects re-run, and DOM nodes are recreated.

open as a page

In the Next.js App Router, a layout.tsx exports a metadata object with a title and an openGraph block, and the page.tsx nested below it exports metadata with only a title. What ends up in the rendered head?

level: middleimportance: should knowfreq 48%

basics

~20 s

Next merges metadata down the segment tree shallowly. The page's title wins, and the layout's openGraph block survives untouched only because the page did not define one — had the page exported its own openGraph, it would replace the parent's object entirely rather than merge field by field.

open as a page

A Next.js App Router dashboard layout fetches an unread-messages count and renders it in the sidebar. Users report the number is right on a hard refresh but never changes as they click between pages under that dashboard. Why, and what are your options?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Shared layouts are preserved across client navigation: Next re-renders only the segments that changed, so a layout above the changed page never re-runs and the value it fetched on first load stays frozen until a full load or an explicit refresh.

open as a page