File Conventions and Special Files
The idea in one sentence
Section titled “The idea in one sentence”In the App Router, folders define route segments and a small set of reserved filenames give each folder its behavior — a folder is only reachable as a URL once it contains a page.
Folders are segments, special files are behavior
Section titled “Folders are segments, special files are behavior”A folder under app/ is a URL segment. But a folder on its own is inert; what it does is decided by the reserved files inside it. Each filename has one job:
page.tsx— the UI for a route, and the thing that makes the segment publicly routable.layout.tsx— a shared wrapper that persists across navigation and nests inside parent layouts.loading.tsx— a Suspense fallback shown while the segment streams in.error.tsx— an error boundary for the segment; it must be a Client Component.not-found.tsx— the UI rendered whennotFound()is called.route.ts— a Route Handler, i.e. an API endpoint instead of a page.template.tsx— like a layout, but it re-mounts a fresh instance on every navigation.
app/ layout.tsx # root layout — wraps everything page.tsx # "/" dashboard/ layout.tsx # wraps everything under /dashboard loading.tsx # fallback while /dashboard loads error.tsx # catches errors in /dashboard page.tsx # "/dashboard" api/ users/ route.ts # "/api/users" — a Route Handler, not a pagepage and layout are the two you use most
Section titled “page and layout are the two you use most”A page receives route params and search params and returns the segment’s UI:
export default async function BlogPost({ params,}: { params: Promise<{ slug: string }>;}) { const { slug } = await params; return <article>Reading: {slug}</article>;}A layout wraps a segment and everything below it. It keeps its state across navigations between sibling pages, so shared chrome like a sidebar does not remount:
export default function DashboardLayout({ children,}: { children: React.ReactNode;}) { return ( <section> <nav>Dashboard nav</nav> {children} </section> );}The root layout is required
Section titled “The root layout is required”Every App Router app must have one root layout at app/layout.tsx. It is the only layout that renders the <html> and <body> tags, because Next.js does not emit them for you:
export default function RootLayout({ children,}: { children: React.ReactNode;}) { return ( <html lang="en"> <body>{children}</body> </html> );}Two rules follow from all this. First, a folder without a page.tsx (or a route.ts) is not routable — you can nest folders purely to organize files and they will never respond to a URL. Second, error.tsx must start with "use client", because error boundaries rely on client-side React.
flowchart LR Folder[dashboard folder] --> Layout[layout wraps and persists] Layout --> Loading[loading is the Suspense fallback] Layout --> Error[error catches failures] Layout --> Page[page is the routable UI] Page --> URL[/dashboard is reachable]