Skip to content
intermediate Phase 2 · App Router, Layouts, and Pages

Nested Layouts

Stack per-section layouts that keep state between visits.

45m
0 problems
Topic Progress 0%

Layout Stacking from Root to Leaf

In the app router, each directory can have its own layout.js or layout.tsx. These layouts stack from the root downward: the root layout wraps the next level, which wraps the next, and so on. This creates a compositional UI where each segment contributes its own surrounding UI. How stacking works: app/layout.tsx (root) is the outermost wrapper. app/dashboard/layout.tsx wraps everything under /dashboard. app/dashboard/settings/layout.tsx wraps everything under /dashboard/settings. Each layout receives a children prop that renders the matched page or child layout for its segment. Layout composition example: app/ ├── layout.tsx (root: html/body, global nav, persists across all nav) ├── dashboard/ │ ├── layout.tsx (dashboard: sidebar, persists across /dashboard and /dashboard/settings) │ │ ├── settings/ │ │ │ └── layout.tsx (settings: breadcrumbs, persists only under /dashboard/settings) │ │ │ └── page.js (the settings page UI) │ │ └── page.js (dashboard settings page UI) │ └── page.js (dashboard home page UI) └── page.js (home page UI) When navigating from /dashboard to /dashboard/settings using next/link: The root layout (app/layout.tsx) stays mounted. The dashboard layout (app/dashboard/layout.tsx) stays mounted. The settings layout (app/dashboard/settings/layout.tsx) mounts for the first time. Only the page.js content unmounts and remounts. Preserving UI state: Because layouts stay mounted across client-side navigation, any state, event listeners, or DOM nodes placed in a layout persist. This is the primary mechanism for keeping an open sidebar, a shopping cart icon count, or a user profile widget visible as the user navigates through a section. This layout persistence model is one of the most powerful differentiators between the Next.js app router and traditional routing approaches, because it enables UI patterns that were previously difficult or impossible to implement without custom JavaScript. The children prop: Each layout's children prop renders the output of the matched child layout or page. A layout typically looks like: export default function DashboardLayout({ children }) { return ( <aside className="sidebar" stays mounted, state persists>{/* sidebar content /}

{children}
{/ renders child layout or page /} ); } Beyond basic UI nesting, the children prop allows for progressive enhancement where each layout layer can add its own wrapping UI while still allowing lower levels to contribute their specific content. This compositional approach means that a change at the root layout level propagates down to all nested segments, while changes at the leaf level only affect that specific route.\n\n*Layout stacking order: The stacking follows a strict hierarchical order. At the top level, app/layout.tsx provides the outermost HTML structure and global UI. Moving down, each directory-level layout adds its own section-specific surrounding UI. For example, app/dashboard/layout.tsx might add a dashboard-specific sidebar and navigation. Deeper levels, like app/dashboard/settings/layout.tsx, add section-specific UI like breadcrumbs or settings-focused actions. The key insight is that layouts don't replace their parents—they wrap around them. When a user navigates from /dashboard to /dashboard/settings using next/link, the root layout and dashboard layout stay mounted throughout the transition, while only the settings layout and the page.js content unmount and remount. This creates a smooth transition experience where the user doesn't lose their place in the application hierarchy.\n\nProgressive UI enhancement: Layout stacking enables progressive UI enhancement patterns. For instance, you might start with a minimal layout on the root and progressively add more UI as you go deeper into the app hierarchy. This is useful for creating applications with different UI requirements at different levels—perhaps the root layout shows a global navigation, the dashboard layout shows a sidebar, and individual page layouts are minimal or even absent. Because layouts persist across navigation, the user's mental model of where they are in the application is maintained, even as different levels of UI are added or removed.\n\nEdge cases and considerations: While layout stacking provides powerful UI composition, there are some edge cases to be aware of. If layouts contain large DOM trees or many event listeners, they can impact initial page load performance and memory usage on older devices or constrained environments. A good rule of thumb is to keep layout UI minimal and to clean up any event listeners when layouts are unmounted. Additionally, if the same layout is used across many routes, changes to that layout file will affect all those routes, so careful coordination is needed in team settings. Code reviews should verify that the layout hierarchy is correct and that the children prop is being used correctly to render the matched page content at each level. In large applications, it's common to have a shared layout component library that ensures consistency across the layout hierarchy while allowing each segment to contribute its own UI.

Interview Framework for Nested Layouts

When asked about nested layouts, a strong answer covers three key areas: 1) Stacking order—the root layout is the outermost wrapper, and each subsequent layout nests within it, creating a hierarchy from root to leaf. Each layout in the hierarchy is responsible for rendering its own surrounding UI (sidebar, header, navigation, etc.) and passing the children prop down to the next level. 2) Persistence across navigation—layouts stay mounted when using next/link, which is why UI like open sidebars persists across route changes within a section. When a user navigates from /dashboard to /dashboard/settings using next/link, the root and dashboard layouts stay mounted, while only the settings page component unmounts and remounts. This is why UI like open sidebars, profile widgets, and theme preferences persist across navigation. This persistence model is a key differentiator between the app router and traditional routing, and interviewers value candidates who can explain why this matters for user experience. 3) State management—layouts are the ideal place for section-level UI state (sidebar open/closed, theme preference, profile widgets), but too much client-side state can lead to memory leaks on refresh. The recommended pattern is to initialize layout state from server data and persist cross-tab consistency via localStorage/sessionStorage if needed. A common pattern is to fetch the user's preferred sidebar state from an API on the server and then persist it in localStorage for cross-tab consistency. Interview framing: When asked about preserving UI state across navigation, a strong answer explains that layouts are the mechanism—because they stay mounted, any state placed in them persists. Mentioning that you initialize from server data and persist to localStorage for cross-tab consistency shows you understand the trade-offs. Discussing the risk of too much client-side layout state (memory leaks on refresh) shows you've thought about edge cases. Typical interview scenario: An interviewer asks: "Your application needs to keep a sidebar open across navigation within a section. How do you implement this?" A strong answer: "I'd use nested layouts, with the sidebar in the dashboard layout. Because layouts stay mounted across navigation via next/link, the sidebar state persists. I'd initialize the sidebar state from server data and persist it to localStorage for cross-tab consistency if needed." Another common question: "What persists across client-side navigation?" The answer is: "The root and intermediate layouts, not page components." Key takeaway: Layouts stack root-to-leaf; layouts persist across navigation; ideal for section-level UI state; initialize from server data; only pages unmount/remount.\n\nAdditional interview insights: Interviewers often follow up with questions about the trade-offs of layout persistence. A strong candidate will discuss both the benefits (persistent sidebars, preserved form state, consistent theming) and the risks (memory usage, stale state, the need for cleanup). They might mention that the decision of what state to place in layouts versus pages or global contexts depends on the specific application requirements, the frequency of navigation, and the need for cross-tab consistency. Another common follow-up question is: "What happens if the user opens your app in a new tab?" The answer typically involves discussing how layout state initialized from server data and persisted to localStorage can provide cross-tab consistency, while purely client-side layout state would be lost. A thoughtful answer demonstrates that you've considered not just the happy path, but also the edge cases and real-world production scenarios.\n\nKey takeaway: Layouts stack root-to-leaf; layouts persist across navigation; ideal for section-level UI state; initialize from server data; only pages unmount/remount; consider cross-tab consistency for layout state.

Quiz

1. How do layouts stack in the app router?

Question 1 options

2. Why do layouts persist across client-side navigation?

Question 2 options

3. What is a common use case for persisting state in layouts?

Question 3 options

4. What should you be cautious about when placing state in layouts?

Question 4 options

Flashcards

Question

How do nested layouts stack in the app router?

Answer

Each segment's layout wraps its children; root is outermost, leaf is innermost. Each receives children with the matched child output.

Question

Why do layouts persist across client-side navigation?

Answer

Layouts stay mounted; only page components unmount/remount when using next/link.

Question

What UI state is ideal for layout persistence?

Answer

Section-level state like sidebar open/closed, theme preference, or profile widget visible within a section.

Question

What is a risk of too much client-side layout state?

Answer

May lead to memory leaks on refresh/new tab.

Question

How can you persist layout state across tabs?

Answer

Initialize from server data and persist to localStorage/sessionStorage for cross-tab consistency.

Revision Notes

Key Takeaways

  • 1. Layouts stack root-downward; each has children prop with child output
  • 2. Layouts persist across navigation; pages unmount/remount
  • 3. Ideal for: sidebar state, theme, section widgets
  • 4. Initialize from server data; persist to localStorage for cross-tab if needed
  • 5. Only page.js unmounts/remounts; layouts stay mounted

Interview Tips

  • • How do nested layouts stack?—root downward; each layout has children with child output
  • • Why do layouts persist across navigation?—they stay mounted via next/link; pages unmount/remount.
  • • What UI state is ideal for layouts?—sidebar open/closed, theme preference, section widgets.
  • • How to avoid memory leaks?—initialize from server data, persist to localStorage for cross-tab consistency if needed.
  • • What only unmounts on navigation?—page components; layouts stay mounted.

Cheat Sheet

Nested Layouts Cheat Sheet

Stacking order: root → segment → sub-segment; each layout wraps its children

Persistence: layouts stay mounted across navigation via next/link; pages unmount/remount

Ideal for: sidebar state, theme, section widgets

State initialization: initialize from server data; persist to localStorage/sessionStorage for cross-tab consistency if needed

Interview quick answers:

  • How do nested layouts stack?—root downward; each layout has children with child output
  • Why do layouts persist across navigation?—they stay mounted via next/link; pages unmount/remount
  • What UI state is ideal for layouts?—sidebar open/closed, theme preference, section widgets
  • How to avoid memory leaks?—initialize from server data, persist to localStorage for cross-tab consistency if needed
  • What only unmounts on navigation?—page components; layouts stay mounted

Continue Learning

Before You Start

Related Reading