The App Router — Files Are the Routing
BeginnerA folder is a URL segment and a handful of reserved filenames give you the page, its layout, its loading state and its error boundary. There is no route configuration to write.
Overview
Next.js has no router configuration file. The shape of the `app` directory is the routing table: each folder becomes a URL segment, and reserved filenames inside it declare what that segment renders. This is quick to learn and has a real payoff — a route's page, layout, loading UI, error boundary and data all sit in one folder, so the whole feature is one place. The cost is that the conventions are load-bearing: a file named wrongly does nothing, silently.
Folders and Reserved Files
The full set, and what each one does.
app/
layout.tsx // root layout — REQUIRED, wraps everything
page.tsx // /
loading.tsx // Suspense fallback for this segment
error.tsx // error boundary ('use client', required)
not-found.tsx // 404 for this segment
global-error.tsx // catches errors in the root layout itself
problems/
page.tsx // /problems
loading.tsx // shown while /problems streams
[slug]/
page.tsx // /problems/two-sum
opengraph-image.tsx
api/
health/route.ts // GET /api/health — a handler, not a page
// Only page.tsx and route.ts make a segment publicly routable. A
// folder of components with no page.tsx is not a URL — which is why
// colocating components inside a route folder is safe.
// Dynamic segments
[slug] // /problems/two-sum -> params.slug
[...path] // catch-all -> params.path is an array
[[...path]] // optional catch-all -> also matches the parentA Page and Its Params
The two props every page receives, and generating static paths.
// app/problems/[slug]/page.tsx
export default async function ProblemPage({ params, searchParams }) {
const problem = await getProblem(params.slug) // /problems/two-sum
const tab = searchParams.tab ?? 'description' // ?tab=solution
...
}
// Reading searchParams makes the route DYNAMIC — it cannot be known
// at build time. If you only need it in one small part of the page,
// read it in a client component with useSearchParams instead, and
// keep the rest static.
// Pre-render the known paths at build time
export async function generateStaticParams() {
const problems = await listProblemSlugs()
return problems.map((slug) => ({ slug }))
}
// Everything returned here becomes a static page. Anything not
// listed is rendered on demand and then cached, unless you forbid it:
export const dynamicParams = false // 404 instead
// In Next 15+, params and searchParams are Promises and must be
// awaited — the single most common upgrade error:
const { slug } = await paramsGroups, Private Folders and Parallel Routes
Organising without changing the URL.
// Route groups: (name) organises without adding a URL segment
app/
(marketing)/
layout.tsx // a marketing shell
page.tsx // /
pricing/page.tsx // /pricing <- not /marketing/pricing
(app)/
layout.tsx // a signed-in shell — a DIFFERENT root layout
dashboard/page.tsx // /dashboard
// Private folders: _name is never routable, for colocated code
app/problems/_components/ProblemCard.tsx
// Parallel routes: render two independent subtrees in one layout
app/
@sidebar/page.tsx
@main/page.tsx
layout.tsx // receives { sidebar, main } as props
// Intercepting routes: show a route as a modal over the current page,
// but as a full page on a direct visit or a refresh — the Instagram
// photo-grid behaviour
app/problems/(.)preview/[slug]/page.tsx
// Parallel and intercepting routes are powerful and easy to overuse.
// Reach for them when you have the specific problem; not before.Key Points to Remember
- 1Folders are URL segments and reserved filenames declare what each segment renders — there is no route config
- 2Only page.tsx or route.ts makes a segment routable, so components can safely be colocated inside route folders
- 3Reading searchParams forces a route to be dynamic; useSearchParams in a small client component keeps the rest static
- 4generateStaticParams pre-renders known dynamic paths at build time
- 5Route groups organise without changing the URL, and _folders are never routable
Interview Questions
Sign in to ask AriaHow does file-based routing work in the App Router?
What is a route group and when would you use one?
What does generateStaticParams do?
Ask Aria about The App Router — Files Are the Routing
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.