Skip to content

File Conventions and Special Files

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 when notFound() 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 page

A page receives route params and search params and returns the segment’s UI:

app/blog/[slug]/page.tsx
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:

app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<section>
<nav>Dashboard nav</nav>
{children}
</section>
);
}

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:

app/layout.tsx
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]
How special files map onto a route segment
Which file makes a route segment publicly reachable at a URL?
What is special about error.tsx?
What lives only in the root layout?
A folder that contains no page.tsx and no route.ts is: