Course outline · 0% complete

0/29 lessons0%

Course overview →

Layouts and navigating with Link

lesson 2-3 · ~10 min · 6/29

Layouts: the shared shell

Every real site repeats its chrome, the fixed framing around the content, on every page: nav bar, footer, fonts. In the React course you solved this by composing components manually on each page. Next.js formalizes it with layout.js:

// app/layout.js  (the required root layout)
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <nav>My Site</nav>
        {children}
      </body>
    </html>
  );
}

Decode it:

  • The root layout must render the html and body elements. It replaces the old index.html.
  • children is the current page. Navigate from / to /about and only children changes.
  • The layout component itself does not re-render or lose state when you move between its pages.

Layouts nest

Drop another layout.js deeper in the tree and it wraps only that section:

app/
├── layout.js          ← wraps everything
└── docs/
    ├── layout.js      ← wraps only /docs/*  (e.g. a sidebar)
    ├── page.js        →  /docs
    └── setup/page.js  →  /docs/setup

Visiting /docs/setup renders root layout → docs layout → the setup page, nested like Russian dolls. This is the same composition-with-children pattern from the React course, applied by the router automatically.

app/layout.js (root: html, body, nav)app/docs/layout.js (sidebar){children} ← the current pagedocs/page.jsdocs/setup/page.jsonly this slot swaps
Nested layouts wrap the page like Russian dolls: the root layout wraps the docs layout, which wraps the current page, and only the innermost page slot swaps out on navigation.

State inside a layout survives navigation

Picture the docs layout containing a search input with text already typed into it. A user navigates from /docs to /docs/setup. The typed text survives.

Layouts do not remount when you navigate between pages inside them. Only the page part, the children slot, is swapped out. Any state living in the docs layout, including the text in that search input, the scroll position, or an open sidebar, is untouched by the move.

That persistence is the whole point of the layout convention. It gives you a place to put state that should outlive individual pages, and it is why a Next.js sidebar does not flicker on every click.

Link: navigation without the reload

A plain <a href="/about"> works, but it triggers a full page reload: the browser throws everything away and starts over. Next.js ships a smarter component:

import Link from "next/link";

<Link href="/about">About</Link>

What Link buys you:

  • Client-side navigation. Only the changing part of the tree is swapped in, and layout state survives, exactly as described above.
  • Prefetching. Next.js can start loading the target page before the click, so navigation feels instant.

Rule of thumb: Link for every internal route, plain anchor tags only for external sites.

Diagnosing a theme picker that keeps resetting

Here is a bug report you will eventually see in real life. A teammate built the site nav out of plain <a href="/pricing"> tags, and users report that the theme picker in the root layout resets on every click.

The fix is to replace those anchors with the Link component from next/link.

Why it works out that way

  • A plain anchor causes a full page reload, which tears down and remounts every component, root layout included, so the theme state is destroyed and recreated at its default.
  • Link performs client-side navigation instead: only the page content swaps, layouts persist, and the chosen theme survives.
  • Next.js ships this navigation component in next/link, so no extra dependency is involved.
BehaviourPlain anchorLink
Page reloadFull reloadNo reload
Layout stateLostPreserved
PrefetchingNoneAutomatic
Use it forExternal sitesInternal routes