You can share UI across pages in the Next.js App Router by placing that UI inside a nested layout instead of copying it into every route file. This is how you avoid repeating a sidebar or nav bar in every page.
Say a dashboard section needs the same sidebar on every page inside it. Add one layout file to the dashboard folder and every route below it gets the sidebar automatically, with no import needed in the page files themselves.
app/
dashboard/
layout.tsx (shared UI for every route below)
page.tsx (served at /dashboard)
settings/
page.tsx (served at /dashboard/settings)Both page files render inside this same layout without importing it or repeating its markup, because the App Router applies a layout to every route nested under its folder.
// app/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div className="dashboard-shell">
<aside>Dashboard sidebar</aside>
<main>{children}</main>
</div>
);
}Open the dashboard page and the settings page in the browser and the sidebar appears on both, even though neither page file mentions it. The layout supplies it once for the whole folder.
Why this beats repeating the UI in every page
Copying a sidebar into every page file means updating every file when the design changes, and it means the browser treats the sidebar as new content on every navigation. A shared layout avoids both problems at once.
When a reader clicks from the dashboard page to the settings page, Next.js keeps the layout mounted and only swaps the content inside main. The sidebar does not flicker or lose its scroll position, because it never leaves the tree during that navigation.
Fetching data for the shared UI
A layout cannot receive data from the page it wraps, so if the sidebar needs its own data, fetch it inside the layout directly instead of trying to pass it down from a page.
// app/dashboard/layout.tsx
import { getNavLinks } from "@/lib/nav";
export default async function DashboardLayout({ children }: { children: React.ReactNode }) {
const links = await getNavLinks();
return (
<div className="dashboard-shell">
<aside>{links.length} nav links loaded</aside>
<main>{children}</main>
</div>
);
}If the page below the layout needs the same data, call getNavLinks again inside the page. Next.js automatically dedupes an identical fetch request made in both places during one render, so this does not trigger a second network round trip. For a database call instead of fetch, wrap the function in React's cache so both places share one result, as shown in Passing Data Between Layouts and Pages in Next.js.
A limit worth knowing
A layout does not re-render on navigation, so it cannot read the query string, which would go stale the moment the URL changes without a re-render to catch it. If the shared UI needs to react to a query string, read it inside a client component using the useSearchParams hook, covered in Next.js params vs searchParams: How to Read URL Parameters, or move that piece into the page itself, which does receive it directly.
Rune AI
Key Insights
- Add a layout to a folder to share its UI with every route inside that folder.
- A layout stays mounted across navigation inside the same segment, so it does not re-render.
- Layouts and the pages they wrap fetch their own data independently.
- Next.js dedupes an identical fetch call made by both a layout and a page.
- A layout cannot read the query string because it does not re-render when it changes.
Frequently Asked Questions
Do I need a layout for every folder?
Can a page pass data up into the layout that wraps it?
Does clicking a link inside a shared layout reload that layout?
Conclusion
A nested layout is the App Router's answer to shared UI. Put a layout file in the folder where the shared UI should start, and every route inside that folder gets it without repeating a single line of markup.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.