The build is not one step. It is a compiler pipeline that turns your app tree into runtime maps.
This page explains what Next.js reads, what it transforms, what it emits, and which runtime later consumes each artifact. Open any stage to see its inputs, the artifact it produces, and the runtime that reads that artifact later.
A Next.js build starts with your project files, but it does not simply concatenate them. It reads configuration, resolves environment variables, classifies modules into runtime graphs, compiles TypeScript and JSX, processes assets, splits server and client boundaries, builds chunks, analyzes routes, prerenders what can be static, writes manifests, and finally reports what was produced.
Build pipeline diagram
Inputs flow left to right into the deployable output
tap any stage ↗
phase mental modelMODEL
02 — graph analysis
The app becomes several graphs, not one bundle.
Next.js and Turbopack have to decide which modules belong to the server runtime, which belong to the browser runtime, which are route handlers, which are assets, and which files are only metadata. The split matters because each graph has a different runtime and a different failure mode.
Graph classification diagram
Shows how imports become server, client, route, asset and proxy graphs
tap any box ↗
03 — App Router DSL
Your folder tree is a routing language.
In the App Router, the tree is not just organization. Folder names are path grammar. Special files are framework keywords. Nesting is layout composition. Dynamic folders are parameters. Route groups are invisible organization. Next.js reads that structure and emits internal route manifests from it.
Filesystem DSL → route map
Folders become segments; special files become behavior
tap a box or file ↗
Special files are keywords
page.tsx
makes a segment publicly renderable as UI.
layout.tsx
wraps the segment and child segments; root layout owns <html> and <body>.
loading.tsx
creates an automatic Suspense fallback for that segment.
route.ts
declares a request handler endpoint, not a React page.
[slug]
declares a dynamic URL parameter.
(group)
organizes files without adding the folder name to the URL.
folder tree → route mapTREE
app/dashboard/settings/page.tsx
↓
/dashboard/settings
app/dashboard/settings/Button.tsx
↓
not a route; just a colocated module
app/api/users/route.ts
↓
GET /api/users
POST /api/users
04 — RSC transport
Initial load can stream HTML and Flight together. Client navigation usually asks for Flight separately.
The browser can paint HTML immediately, but React also needs the serialized Server Component tree so it can reconcile what the server rendered and hydrate Client Component boundaries. That serialized tree is the Flight / RSC payload.
Flight payload only
The existing document stays alive.
The client router receives the next RSC tree.
React reconciles the new server output.
05 — manifests
A manifest is a map for a later reader.
The word “manifest” causes confusion because there are two very different categories. Your app/manifest.* is browser-facing metadata for installability and icons. Internal .next/ manifests are build products that Next, React, the router, the deployment adapter, or the cache system read later.
Manifest families diagram
Public browser manifest vs internal runtime manifests
tap any box ↗
example shapeJSON
06 — .next output
The build output is a directory of runtime artifacts.
.next/ is not just “the bundle.” It contains server-side bundles, browser chunks, static assets, generated HTML/RSC artifacts, route metadata, cache data, and traces that explain which files a deployment needs to copy.
.next/ output map
What gets emitted and who reads it
tap any box ↗
example paths.NEXT
07 — handbook
The deeper rule: every artifact exists because something later needs to read it.
Lock this in: the tree is the config, the filenames are the keywords, the graphs decide runtime ownership, and the manifests are the maps that let runtime readers find the correct thing later.
tap any concept to expand ↗
Initialization / configLoads project-level rules before the graph is trusted: Next config, TypeScript config, compiler options, output mode, experimental flags, redirects, image settings and environment conventions.
Env inliningBrowser-safe public values can be replaced in client bundles. Server-only values must remain server-only and must not leak into client chunks.
Tree shaking / DCEDead code elimination removes unreachable exports and branches after the graph and transforms make dependencies explicit enough to prove what is unused.
Chunking / prefetchThe client graph is sliced into route-aware chunks so navigation can fetch likely-needed code without shipping the whole app on first paint.
MinificationProduction code is made smaller after semantic transforms. The goal is less transfer and less parse work, without changing runtime meaning.
Reporting / budgetingThe final stage is feedback: route sizes, chunk relationships, slow prerenders, oversized assets and accidental client bundle growth.