Understanding Pages and Layouts in Next.js
Once you understand that app/ powers routing through folder structure, the next question is: how do you avoid repeating the same navbar, footer, and wrapper markup on every single page? The App Router answers this with two distinct, purpose-built files — page.tsx and layout.tsx — that together let you define unique content per route while sharing common UI across many routes without duplication or unnecessary re-rendering.
This lesson goes deeper into how these two files interact, what a root layout is and why every App Router project must have one, and how nested layouts let you apply different shared UI to different sections of a site — for example, a marketing layout for public pages and a completely different dashboard layout for authenticated pages.
Learning Objectives
- Explain the distinct responsibilities of page.tsx and layout.tsx.
- Understand why every App Router project requires a root layout.
- Build nested layouts that apply shared UI to specific sections of a site.
- Recognize that layouts persist across navigation without re-rendering.
- Identify how the children prop connects a layout to its nested content.
Core Definitions
- page.tsx: The file that defines the unique, primary content for a specific route.
- layout.tsx: The file that defines UI shared across a page and any of its nested routes, wrapping them via a children prop.
- Root layout: The required top-level layout.tsx at app/layout.tsx that wraps the entire application, including the mandatory <html> and <body> tags.
- Nested layout: A layout.tsx placed inside a subfolder of app/, applying additional shared UI only to routes within that subfolder.
- children prop: A special prop automatically passed to a layout component, representing whatever page or nested layout is rendered inside it.
- Route segment: A single folder within the app/ directory that corresponds to one part of a URL path.
Detailed Explanation
Every App Router project must have exactly one root layout at app/layout.tsx. This file is special: it must contain the <html> and <body> tags, since it's the outermost wrapper for your entire application — no other layout can replace this responsibility. Inside the root layout, a children prop represents whatever page or nested layout should render inside it, and React automatically supplies this value; you never pass it manually.
page.tsx and layout.tsx solve different problems. page.tsx answers 'what unique content lives at this exact URL?' while layout.tsx answers 'what shared UI should wrap this page and everything nested beneath it?' A single layout.tsx can wrap many page.tsx files if those pages live in nested folders beneath it.
This is where nested layouts become powerful. Imagine a project with app/layout.tsx (root layout with global navbar) and app/dashboard/layout.tsx (a second layout containing a sidebar, specific to dashboard pages). Any page inside app/dashboard/ — such as app/dashboard/settings/page.tsx — automatically renders inside BOTH layouts: first wrapped by the dashboard sidebar layout, which is itself wrapped by the root layout's navbar. Pages outside app/dashboard/, like the homepage, only pass through the root layout, never seeing the sidebar.
A crucial performance detail: layouts persist across navigation within their scope. If a user clicks from /dashboard/settings to /dashboard/billing, the dashboard sidebar layout does NOT re-render or re-fetch its data — only the page.tsx content inside it swaps out. This preserves UI state (like scroll position or open menus) in the layout and avoids redundant work, a meaningful advantage over full-page reloads or layouts re-implemented per-page in older routing systems.
Diagram Description
Visualize a nested wrapping diagram:
app/layout.tsx (ROOT — has <html>/<body>, contains global Navbar)
└── app/page.tsx → Homepage: Navbar only
└── app/dashboard/layout.tsx (Sidebar)
└── app/dashboard/page.tsx → Navbar + Sidebar + Dashboard home
└── app/dashboard/settings/page.tsx → Navbar + Sidebar + Settings content
└── app/dashboard/billing/page.tsx → Navbar + Sidebar + Billing content
Navigating between settings <-> billing: Sidebar layout stays mounted, only inner page.tsx content swaps.
Comparison Table
| File | Required? | Responsibility | Re-renders on navigation within its scope? |
|---|---|---|---|
| app/layout.tsx | Yes (exactly one, at root) | Wraps entire app; must include <html>/<body> | No — persists |
| app/[section]/layout.tsx | Optional | Wraps only routes nested inside [section] | No — persists within that section |
| app/page.tsx | Yes, per route | Unique content for that specific URL | Yes — swaps per route |
Next.js Practical Example
// app/layout.tsx — ROOT layout (required, has <html>/<body>)
import './globals.css';
import Navbar from '@/components/Navbar';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Navbar />
{children}
</body>
</html>
);
}
// app/dashboard/layout.tsx — NESTED layout, only wraps /dashboard/* routes
import Sidebar from '@/components/Sidebar';
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div style={{ display: 'flex' }}>
<Sidebar />
<section>{children}</section>
</div>
);
}
// app/dashboard/settings/page.tsx — unique page content
export default function SettingsPage() {
return <h1>Account Settings</h1>;
}
When a user visits /dashboard/settings, Next.js composes three pieces automatically: RootLayout wraps everything with the Navbar, DashboardLayout wraps dashboard routes with the Sidebar, and SettingsPage supplies the unique heading content. The children prop is how each layout knows what to render inside itself — RootLayout's children resolves to DashboardLayout's entire output, and DashboardLayout's children resolves to SettingsPage's output. If the user then navigates to /dashboard/billing, only the innermost page.tsx content changes; both RootLayout and DashboardLayout remain mounted without re-rendering.
Industry Examples
- SaaS products commonly use a root layout for marketing pages (navbar, footer) and a completely separate dashboard layout (sidebar, top bar) applied only to authenticated app routes.
- E-commerce platforms use a nested checkout layout that strips away the main site navbar and footer during checkout to reduce distractions and cart abandonment.
- Documentation sites use a nested docs layout with a persistent sidebar table of contents, so navigating between doc pages doesn't reset scroll position or collapse expanded menu sections.
- Admin panels use nested layouts per major section (e.g., app/admin/users/layout.tsx vs app/admin/billing/layout.tsx) to show section-specific sub-navigation.
- Multi-tenant platforms sometimes use nested layouts keyed by an organization or workspace segment, so each workspace can show a customized header while still inheriting the app-wide root layout.
Interview Questions and Answers
Q1. What is the difference between page.tsx and layout.tsx in the Next.js App Router?
page.tsx defines the unique content rendered for a specific route/URL. layout.tsx defines shared UI that wraps a page and any of its nested routes, such as a navbar or sidebar, and persists across navigation within its scope rather than re-rendering per page.
Q2. Why must every Next.js App Router project have a root layout?
The root layout at app/layout.tsx is required because it must contain the <html> and <body> tags, which are mandatory for a valid HTML document. Every other page and nested layout in the application renders inside this root layout via its children prop.
Q3. How does the children prop work in a layout component?
React and Next.js automatically pass whatever is nested inside a layout — either a page or another nested layout — as the children prop. The layout component renders {children} at the position where nested content should appear, without needing to manually specify what that content is.
Q4. What happens to a layout when a user navigates between two pages nested within it?
The layout persists and does not re-render or lose its state; only the page.tsx content inside it swaps out. This means UI like scroll position, open dropdowns, or in-progress form state within the layout itself is preserved across navigation.
Q5. Can a Next.js app have multiple layouts?
Yes. Beyond the single required root layout, any folder within app/ can define its own layout.tsx, creating a nested layout that applies only to routes within that folder and its subfolders, while still being wrapped by all layouts above it.
MCQs With Answers
1. Which file must contain the <html> and <body> tags in an App Router project?
- Any page.tsx
- The root app/layout.tsx
- globals.css
- next.config.js
Answer: B. The root app/layout.tsx
Explanation: The root layout is the outermost wrapper for the entire application and is required to include the <html> and <body> tags.
2. What does the children prop represent inside a layout component?
- The layout's own static content
- Whatever page or nested layout is rendered inside it
- A list of all routes in the app
- The site's navigation menu
Answer: B. Whatever page or nested layout is rendered inside it
Explanation: children is automatically supplied by Next.js/React to represent the nested page or layout that should render at that position.
3. If app/dashboard/layout.tsx exists, which routes does it wrap?
- Every route in the entire app
- Only routes nested inside app/dashboard/
- Only the homepage
- No routes until manually imported
Answer: B. Only routes nested inside app/dashboard/
Explanation: A nested layout only applies to routes within its own folder and any subfolders beneath it, not the entire application.
4. What happens to a shared layout's state when navigating between two pages it wraps?
- It resets completely
- It persists without re-rendering
- It throws an error
- It duplicates itself
Answer: B. It persists without re-rendering
Explanation: Layouts remain mounted across navigation within their scope; only the inner page.tsx content changes, preserving the layout's own state.
5. How many root layouts can a single Next.js App Router project have?
- Zero
- Exactly one
- Unlimited
- One per page
Answer: B. Exactly one
Explanation: There must be exactly one root layout at app/layout.tsx, since it uniquely provides the required <html> and <body> tags for the whole application.
Common Mistakes to Avoid
- Forgetting to include <html> and <body> tags in the root layout, causing invalid HTML structure.
- Manually passing a children prop into a layout component instead of letting Next.js supply it automatically.
- Duplicating a navbar inside every page.tsx instead of placing it once in a shared layout.tsx.
- Expecting a nested layout to affect routes outside its own folder, when it only applies to its own subtree.
- Assuming a layout re-fetches data or resets state on every navigation, when in fact it persists across navigation within its scope.
Interview Notes
- The root layout at app/layout.tsx is mandatory and must include <html> and <body> tags.
- page.tsx = unique content per route; layout.tsx = shared UI wrapping a page and its nested routes.
- The children prop is automatically supplied to a layout, representing nested page or layout content.
- Nested layouts apply only to routes within their own folder and subfolders, not the whole app.
- Layouts persist across navigation within their scope, avoiding unnecessary re-renders of shared UI.
Key Takeaways
- page.tsx and layout.tsx together let you share UI without duplicating it across every route.
- The mandatory root layout is where global concerns — HTML structure, global styles, app-wide navigation — belong.
- Nested layouts scale this same idea to specific sections of a site, like a dashboard or checkout flow.
- Layout persistence across navigation is a meaningful performance and UX advantage baked into the App Router's design.
Summary
In the Next.js App Router, page.tsx and layout.tsx divide responsibilities cleanly: page.tsx defines unique content for a specific URL, while layout.tsx defines shared UI wrapping a page and any nested routes beneath it. Every project requires exactly one root layout at app/layout.tsx, which must contain the <html> and <body> tags and wraps the entire application. Additional nested layouts can be added inside any subfolder to apply section-specific shared UI, such as a dashboard sidebar. Layouts receive nested content automatically via the children prop and, critically, persist across navigation within their scope rather than re-rendering, preserving UI state and avoiding redundant work.