# blade47/next.js Wiki
## Technical docs: System Overview
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/getting-started/system-overview
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next/src/api/server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts)
- [packages/next/src/server/app-render/app-render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx)
- [packages/next/src/server/render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx)
- [packages/next/src/server/next-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts)
- [packages/next/src/api/navigation.react-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.react-server.ts)
- [packages/next/src/client/index.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/index.tsx)
- [packages/next/src/api/navigation.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts)
- [packages/next/src/api/router.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/router.ts)
- [packages/next/navigation.js](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js)
- [packages/next/src/server/after/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts)
- [packages/next/types.js](https://github.com/blade47/next.js/blob/main/packages/next/types.js)
- [packages/next/src/client/next-dev.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts)
- [packages/next/app.js](https://github.com/blade47/next.js/blob/main/packages/next/app.js)
- [packages/next/src/server/app-render/entry-base.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/entry-base.ts)
- [packages/next/src/client/components/app-router.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router.tsx)
- [packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/pages/index.ts](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/pages/index.ts)
- [packages/next/navigation.d.ts](https://github.com/blade47/next.js/blob/main/packages/next/navigation.d.ts)
- [packages/next/src/client/app-index.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx)
- [packages/create-next-app/templates/default/js/pages/index.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default/js/pages/index.js)
- [packages/next/src/server/next.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts)
- [packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/pages/index.ts](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/pages/index.ts)
- [packages/next/src/api/app.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/api/app.tsx)
- [packages/next/src/cli/next-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts)
- [packages/next/src/server/route-modules/pages/module.compiled.d.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/pages/module.compiled.d.ts)
- [packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts)
- [packages/next/src/api/link.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/link.ts)
- [packages/next/script.js](https://github.com/blade47/next.js/blob/main/packages/next/script.js)
- [packages/create-next-app/templates/app/js/app/page.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app/js/app/page.js)
- [packages/next/client.d.ts](https://github.com/blade47/next.js/blob/main/packages/next/client.d.ts)
## Overview
Next.js delivers a comprehensive full-stack framework architecture designed to bridge server-side request processing, multi-paradigm rendering engines, and client-side hydration runtimes. By establishing robust abstractions across server execution contexts and browser environments, the framework solves complex web delivery challenges such as hybrid static-dynamic page generation, streaming component payloads, and seamless client-side navigation. Core design decisions integrate modular route matching, server action handlers, and diagnostic tooling into unified entrypoints that streamline application development and deployment. Sources: [packages/next/src/server/base-server.ts:98-102](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L98-L102), [packages/next/src/server/app-render/app-render.tsx:54-65](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L54-L65), [packages/next/src/client/index.tsx:190-208](https://github.com/blade47/next.js/blob/main/packages/next/src/client/index.tsx#L190-L208)
## Server Architecture and Request Handling
### Overview
The server architecture rests upon a multi-layered abstraction that bridges high-level framework wrappers and environment-specific node infrastructure. Initialization operations flow through entrypoint modules that configure runtime environments, cryptographic polyfills, and module loaders before instantiating concrete request handlers. Sources: [packages/next/src/server/next.ts:10-13](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L10-L13), [packages/next/src/server/next-server.ts:1-4](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L1-L4)
### Server Abstraction Layer
The server architecture delegates initialization and routing behaviors through a structured wrapper pattern. The public entrypoint `NextServer` delegates execution to `NextNodeServer`, which inherits core routing and lifecycle management logic from the server base implementation in `packages/next/src/server/base-server.ts`. Sources: [packages/next/src/server/base-server.ts:69-70](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L69-L70), [packages/next/src/server/next.ts:183-185](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L185), [packages/next/src/server/next-server.ts:69-70](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L69-L70)
```mermaid
graph TD
A[NextServer] -->|loads implementation| B[NextNodeServer]
B -->|inherits core routing| C[Base Server Layer]
C --> D[Route Matcher Managers]
C --> E[Response Cache]
```
Sources: [packages/next/src/server/base-server.ts:69-70](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L69-L70), [packages/next/src/server/next.ts:183-185](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L185), [packages/next/src/server/next-server.ts:69-70](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L69-L70)
When custom servers invoke deprecated methods, `NextServer` intercepts them and logs warnings containing guidance toward modern request handler alternatives. Sources: [packages/next/src/server/next.ts:88-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L88-L114)
| Deprecated Method | Migration Guidance | Sources |
| :--- | :--- | :--- |
| `setAssetPrefix` | Please configure `assetPrefix` in `next.config.js` instead. | [packages/next/src/server/next.ts:92-92](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L92-L92) |
| `logError` | Please use application logging instead. | [packages/next/src/server/next.ts:93-93](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L93-L93) |
| `revalidate` | Please use documented application revalidation APIs instead. | [packages/next/src/server/next.ts:95-95](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L95-L95) |
| `render` | Please use `app.getRequestHandler()` with an adjusted parsed URL instead. | [packages/next/src/server/next.ts:96-97](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L96-L97) |
| `renderError` | Please use `app.getRequestHandler()` with an adjusted parsed URL instead. | [packages/next/src/server/next.ts:100-101](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L100-L101) |
| `render404` | Please use `app.getRequestHandler()` with an adjusted parsed URL instead. | [packages/next/src/server/next.ts:104-105](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L104-L105) |
Sources: [packages/next/src/server/next.ts:88-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L88-L114)
### Request Routing and Lifecycle Execution
Incoming HTTP traffic enters through request handlers mapped to node incoming messages and server responses. Dynamic request matching utilizes specialized providers for app pages, app routes, pages APIs, and standard pages routes, coordinating via route matcher managers. Sources: [packages/next/src/server/base-server.ts:98-102](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L98-L102), [packages/next/src/server/next-server.ts:144-149](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L144-L149)
> [!WARNING]
> Middleware matcher configurations are validated against active manifest definitions using cached weak maps; invalid matcher arrays trigger immediate invariant exceptions during request resolution. Sources: [packages/next/src/server/next-server.ts:151-167](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L151-L167)
## App Router Rendering Pipeline
### Overview
The App Router rendering subsystem coordinates server component execution, React Server Component (RSC) Flight streaming, and staged prerendering. Rendering operations are driven by entrypoint modules and stream operations that bridge asynchronous storage layers (`workAsyncStorage` and `workUnitAsyncStorage`) with React's server rendering pipelines. Sources: [packages/next/src/server/app-render/app-render.tsx:18-28](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L18-L28), [packages/next/src/server/app-render/entry-base.ts:1-15](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/entry-base.ts#L1-L15)
### Flight Streaming and Server Components Execution
The Server Components runtime environment leverages serialization and parsing utilities exported via base entrypoints. Streaming operations bridge request lifecycles with React Server Component streams, selectively configuring Node.js or Web stream operations based on `process.env.__NEXT_USE_NODE_STREAMS` and runtime capabilities. Sources: [packages/next/src/server/app-render/entry-base.ts:1-40](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/entry-base.ts#L1-L40), [packages/next/src/server/app-render/app-render.tsx:54-65](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L54-L65)
```mermaid
graph TD
A[Incoming RSC Request] -->|workAsyncStorage| B[App Render Subsystem]
B -->|React Flight Stream| C{Runtime Environment}
C -->|Edge / Web Streams| D[Web Stream Operations]
C -->|Node Streams Enabled| E[Node Stream Operations]
D --> F[Serialized Flight Payload]
E --> F
```
Sources: [packages/next/src/server/app-render/app-render.tsx:18-28](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L18-L28), [packages/next/src/server/app-render/entry-base.ts:1-38](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/entry-base.ts#L1-L38)
> [!NOTE]
> `patchFetch` explicitly wires up `workAsyncStorage` and `workUnitAsyncStorage` to leverage React's experimental postponement and cache integration hooks during server component execution. Sources: [packages/next/src/server/app-render/entry-base.ts:117-124](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/entry-base.ts#L117-L124)
### Dynamic Rendering and Prerender Stream Operations
The pipeline manages static generation and dynamic fallback behaviors across multiple stream continuation functions. These operations handle prerender states, prelude processing, and fallback recovery. Sources: [packages/next/src/server/app-render/app-render.tsx:42-47](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L42-L47)
| Stream Operation Function | Target Prerender / Resume Behavior | Sources |
| :--- | :--- | :--- |
| `continueFizzStream` | Continues standard server-side HTML Fizz rendering streams | [packages/next/src/server/app-render/app-render.tsx:42-42](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L42-L42) |
| `continueDynamicPrerender` | Resumes or proceeds with dynamic prerendering blocks | [packages/next/src/server/app-render/app-render.tsx:43-43](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L43-L43) |
| `continueStaticPrerender` | Executes or resumes static prerendering output | [packages/next/src/server/app-render/app-render.tsx:44-44](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L44-L44) |
| `continueDynamicHTMLResumeNode` | Resumes dynamic HTML rendering on Node.js streams | [packages/next/src/server/app-render/app-render.tsx:45-45](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L45-L45) |
| `continueDynamicHTMLResumeWeb` | Resumes dynamic HTML rendering on Web standard streams | [packages/next/src/server/app-render/app-render.tsx:46-46](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L46-L46) |
| `continueStaticFallbackPrerender` | Generates static fallback structures during prerender bailout | [packages/next/src/server/app-render/app-render.tsx:47-47](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L47-L47) |
Sources: [packages/next/src/server/app-render/app-render.tsx:42-47](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L42-L47)
> [!WARNING]
> Accessing dynamic request parameters or headers without proper suspense boundaries or dynamic configuration triggers static generation bailouts via `StaticGenBailoutError` or dynamic tracking flags. Sources: [packages/next/src/server/app-render/app-render.tsx:141-154](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L141-L154)
## Pages Router Rendering Engine
### Overview
The Pages Router rendering engine governs legacy document generation, initial props evaluation, and DOM serialization within `packages/next/src/server/render.tsx`. It manages server-side request routing state, handles previews, injects style registries like styled-jsx, and evaluates data fetching methods under tracked telemetry spans. Sources: [packages/next/src/server/render.tsx:431-893](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L431-L893)
### Execution Lifecycle and Data Fetching Call Chain
The rendering engine initializes the request context and server router before invoking props loading and static generation checks. The call sequence progresses through these specific internal functions:
`tryGetPreviewData()` → `ServerRouter` instantiation → `adaptForAppRouterInstance()` → `loadGetInitialProps()` → `getTracer().trace()`
Sources: [packages/next/src/server/render.tsx:694-880](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L694-L880)
> [!NOTE]
> When `isSSG` and `!isFallback` are true, `getTracer().trace()` wraps route data evaluation under tracked spans with attributes including `'next.route'`. Sources: [packages/next/src/server/render.tsx:875-886](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L875-L886)
### Document Context and Serialization Handlers
The rendering engine configures helper functions and context properties within `ctx` to execute document rendering and fallback operations. Error serialization adapts depending on whether `dev` mode is active, utilizing `errorToJSON` or returning a standard internal server error structure. Sources: [packages/next/src/server/render.tsx:431-447](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L431-L447), [packages/next/src/server/render.tsx:814-846](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L814-L846)
| Helper Function or Context Property | Return Type / Behavior | Sources |
| :--- | :--- | :--- |
| `serializeError` | Returns `errorToJSON(err)` in development, or a 500 Internal Server Error object in production | [packages/next/src/server/render.tsx:431-447](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L431-L447) |
| `getSafariCacheBusterQueryString` | In dev server mode with Safari user-agents (excluding Chrome), returns a timestamp query string `?ts=...` | [packages/next/src/server/render.tsx:449-457](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L449-L457) |
| `ctx.AppTree` | Renders the page tree wrapped in `AppContainerWithIsomorphicFiberStructure` | [packages/next/src/server/render.tsx:824-830](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L824-L830) |
| `ctx.defaultGetInitialProps` | Asynchronously executes `docCtx.renderPage`, flushes style registry styles, and returns `{ html, head, styles }` | [packages/next/src/server/render.tsx:831-845](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L831-L845) |
Sources: [packages/next/src/server/render.tsx:431-457](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L431-L457), [packages/next/src/server/render.tsx:824-845](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L824-L845)
## Client Navigation and Hydration Runtime
### Overview
The client navigation and hydration runtime manages bootstrap lifecycles, script streaming, browser history synchronization, and DOM hydration mechanisms across client entry points. It orchestrates initial payload extraction from `__NEXT_DATA__` and streams React Server Component chunks via the global `__next_f` flight buffer. Sources: [packages/next/src/client/index.tsx:1-64](https://github.com/blade47/next.js/blob/main/packages/next/src/client/index.tsx#L1-L64), [packages/next/src/client/app-index.tsx:38-110](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L38-L110)
### Flight Stream and Chunk Call Chain
The client app bootstrap consumes and decodes streamed server payloads by registering a readable stream controller and parsing structured flight segments. The execution proceeds through these exact functions:
`nextServerDataLoadingGlobal.forEach()` → `nextServerDataCallback()` → `nextServerDataRegisterWriter()` → `new ReadableStream()` → `ReactDOMClient` hydration
Sources: [packages/next/src/client/app-index.tsx:79-188](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L79-L188)
> [!NOTE]
> Flight segments utilize identifier codes (`0` through `3`) to distinguish bootstrap initiation, partial response text, form state, and base64 binary chunks. Sources: [packages/next/src/client/app-index.tsx:58-110](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L58-L110)
### Flight Segment Types and Buffering Protocol
The client flight protocol processes incoming array tuples assigned to `window.__next_f`. Chunk data is buffered if the stream writer is not yet registered, and later enqueued or base64-decoded. Sources: [packages/next/src/client/app-index.tsx:58-110](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L58-L110)
| Flight Segment Type | Tuple Structure | Action and Handling | Sources |
| :--- | :--- | :--- | :--- |
| Bootstrap Initiation | `[isBootStrap: 0]` | Initializes `initialServerDataBuffer = []` | [packages/next/src/client/app-index.tsx:59-81](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L59-L81) |
| Response Partial | `[isNotBootstrap: 1, responsePartial: string]` | Enqueues encoded string chunks to `initialServerDataWriter` or pushes to buffer | [packages/next/src/client/app-index.tsx:60-60](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L60-L60), [packages/next/src/client/app-index.tsx:82-90](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L82-L90) |
| Form State | `[isFormState: 2, formState: any]` | Assigns form state data to `initialFormStateData` | [packages/next/src/client/app-index.tsx:61-61](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L61-L61), [packages/next/src/client/app-index.tsx:91-92](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L91-L92) |
| Binary Data | `[isBinary: 3, responseBase64Partial: string]` | Decodes base64 string via `atob()` into a `Uint8Array` chunk | [packages/next/src/client/app-index.tsx:62-62](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L62-L62), [packages/next/src/client/app-index.tsx:93-109](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L93-L109) |
Sources: [packages/next/src/client/app-index.tsx:58-110](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L58-L110)
### History State and Hydration Design Choices
App Router navigation synchronizes state into browser history entries utilizing internal keys to distinguish handlers. Sources: [packages/next/src/client/components/app-router.tsx:71-99](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router.tsx#L71-L99)
| Design Choice | Benefit | Cost | Sources |
| :--- | :--- | :--- | :--- |
| Shortened History Identifiers (`__NA` vs `__N`) | Enables precise runtime dispatch selection between App Router and legacy router without heavy parsing | Requires strict adherence to internal property naming conventions across navigation frames | [packages/next/src/client/components/app-router.tsx:79-86](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router.tsx#L79-L86) |
| Buffer teeing for Cache Components (`__NEXT_CACHE_COMPONENTS`) | Allows truncation of inline Flight streams at static stage boundaries for caching | Introduces overhead by duplicating stream consumption channels conditionally | [packages/next/src/client/app-index.tsx:194-202](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L194-L202) |
Sources: [packages/next/src/client/components/app-router.tsx:79-86](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router.tsx#L79-L86), [packages/next/src/client/app-index.tsx:194-202](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L194-L202)
> [!WARNING]
> Accessing or mutating history state properties without retaining `__NA` or `__PRIVATE_NEXTJS_INTERNALS_TREE` breaks App Router state restoration during back/forward browser navigation. Sources: [packages/next/src/client/components/app-router.tsx:73-86](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router.tsx#L73-L86), [packages/next/src/client/components/app-router.tsx:114-128](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router.tsx#L114-L128)
## Public Surface and Exported Submodules
### Overview
Next.js exposes its core entrypoints, submodules, and client navigation utilities through well-defined API definitions and top-level CommonJS entry files. These modules bridge package-level requires with internal client components, server web exports, links, scripts, and navigation primitives. Sources: [packages/next/navigation.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1-L2), [packages/next/app.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1-L2), [packages/next/script.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/script.js#L1-L2), [packages/next/client.d.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/client.d.ts#L1-L2)
### Package Entrypoints and Exports
The package layout delegates runtime resolution to distribution directories via CommonJS wrapper modules and TypeScript API source files. Sources: [packages/next/navigation.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1-L2), [packages/next/app.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1-L2), [packages/next/script.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/script.js#L1-L2)
| Entrypoint File | Export Source / Target | Purpose / Module Type | Sources |
| :--- | :--- | :--- | :--- |
| `navigation.js` | `require('./dist/client/components/navigation')` | Root navigation module export for client components | [packages/next/navigation.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1-L2) |
| `app.js` | `require('./dist/pages/_app')` | Pages router root application component export | [packages/next/app.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1-L2) |
| `script.js` | `require('./dist/client/script')` | Script optimization component export | [packages/next/script.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/script.js#L1-L2) |
Sources: [packages/next/navigation.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1-L2), [packages/next/app.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1-L2), [packages/next/script.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/script.js#L1-L2)
### Client and Server API Definitions
API definitions bridge public TypeScript interfaces with internal runtime modules. Sources: [packages/next/client.d.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/client.d.ts#L1-L2), [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2)
| Entrypoint File | Export Source / Target | Purpose / Module Type | Sources |
| :--- | :--- | :--- | :--- |
| `client.d.ts` | `export * from './dist/client/index'` | TypeScript type definitions for client entrypoints | [packages/next/client.d.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/client.d.ts#L1-L2) |
| `src/api/server.ts` | `export * from '../server/web/exports/index'` | Server-side web export utilities | [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2) |
| `src/api/navigation.ts` | `export * from '../client/components/navigation'` | Client navigation API exports | [packages/next/src/api/navigation.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts#L1-L2) |
| `src/api/navigation.react-server.ts` | `export * from '../client/components/navigation.react-server'` | React server component navigation exports | [packages/next/src/api/navigation.react-server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.react-server.ts#L1-L2) |
| `src/api/link.ts` | `export { default } from '../client/link'`, `export * from '../client/link'` | Link component default and named exports | [packages/next/src/api/link.ts:1-3](https://github.com/blade47/next.js/blob/main/packages/next/src/api/link.ts#L1-L3) |
Sources: [packages/next/client.d.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/client.d.ts#L1-L2), [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2), [packages/next/src/api/navigation.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts#L1-L2), [packages/next/src/api/navigation.react-server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.react-server.ts#L1-L2), [packages/next/src/api/link.ts:1-3](https://github.com/blade47/next.js/blob/main/packages/next/src/api/link.ts#L1-L3)
> [!NOTE]
> Server API exports re-export the entire server web surface via `export * from '../server/web/exports/index'`, providing edge runtime primitives and web APIs directly to server bundles. Sources: [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2)
## Developer Tooling and Diagnostics Subsystem
### Overview
The developer tooling and diagnostics subsystem manages the integration of development environment services, client-side hot module replacement bootstrap routines, and command-line system introspection tasks. It bridges the gap between running development client bundles and platform-level diagnostic reporting utilities. Sources: [packages/next/src/client/next-dev.ts:1-25](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts#L1-L25), [packages/next/src/cli/next-info.ts:1-609](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L1-L609)
### Development Client Bootstrap and HMR Integration
Client-side development initialization begins with `next-dev.ts`, which attaches global window bindings and wires up the Hot Module Replacement (HMR) client. Sources: [packages/next/src/client/next-dev.ts:1-25](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts#L1-L25)
```typescript
const devClient = initHMR()
initialize({ devClient })
.then(({ assetPrefix }) => {
return pageBootstrap(assetPrefix)
})
.catch((err) => {
console.error('Error was not caught', err)
})
```
Sources: [packages/next/src/client/next-dev.ts:17-24](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts#L17-L24)
The window object exposes `version`, a live-binded `router` getter, and an event `emitter`. Sources: [packages/next/src/client/next-dev.ts:8-15](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts#L8-L15)
### Diagnostic CLI and System Inspection Tasks
The `next-info` command-line utility provides standard and verbose diagnostic reporting for debugging environment and binary issues. It collects OS metadata, binary versions, configuration properties, and shared object linkage. Sources: [packages/next/src/cli/next-info.ts:14-608](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L14-L608)
| Task Title | Target Platforms | Purpose / Action Executed | Sources |
| :--- | :--- | :--- | :--- |
| `Host system information` | default (`win32`, `linux`, `darwin`) | Collects WSL status, Docker container detection, and CI environment flags | [packages/next/src/cli/next-info.ts:276-301](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L276-L301) |
| `Next.js installation` | default (`win32`, `linux`, `darwin`) | Enumerates Node version, package managers (`npm`, `yarn`, `pnpm`), relevant packages, and output config | [packages/next/src/cli/next-info.ts:302-330](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L302-L330) |
| `Node.js diagnostic report` | default (`win32`, `linux`, `darwin`) | Retrieves `process.report?.getReport()` and strips sensitive header fields | [packages/next/src/cli/next-info.ts:331-365](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L331-L365) |
| `next-swc installation` | default (`win32`, `linux`, `darwin`) | Verifies `loadBindings()` or inspects target triples and fallback directories | [packages/next/src/cli/next-info.ts:366-468](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L366-L468) |
| `next-swc shared object dependencies` | platform-specific (`linux`, `win32`, `darwin`) | Invokes system tools (`ldd`, `dumpbin.exe`, `otool`, `dyld_info`) to check shared library resolution | [packages/next/src/cli/next-info.ts:473-530](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L473-L530) |
Sources: [packages/next/src/cli/next-info.ts:270-531](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L270-L531)
> [!WARNING]
> The Node.js diagnostic report sanitizes sensitive data by explicitly deleting `header.cwd`, `header.commandLine`, `header.host`, `header.cpus`, and `header.networkInterfaces` prior to JSON serialization. Sources: [packages/next/src/cli/next-info.ts:346-352](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L346-L352)
## Related
- [[Quick Start]]
- [[Project Structure]]
- [[Server Request Lifecycle]]
---
## Technical docs: Client Change Subscription Flow
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/how-it-works/client-change-subscription-flow
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/dev/hot-reloader-turbopack.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts)
- [packages/next/src/shared/lib/turbopack/utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts)
- [packages/next/src/shared/lib/magic-identifier.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/magic-identifier.ts)
## Overview
### Overview of Client Change Subscriptions and Error Deobfuscation
The `SubscribeToClientChanges` to `RemoveFreeCallWrapper` execution flow handles real-time updates and diagnostic message processing between Turbopack and the Next.js development server. When code changes occur, client subscriptions stream compilation events and issues into Next.js, where they undergo rigorous formatting, ANSI styling, and identifier deobfuscation to present clean, readable error messages to developers.
Sources: [packages/next/src/server/dev/hot-reloader-turbopack.ts:787-827](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts#L787-L827), [packages/next/src/shared/lib/turbopack/utils.ts:53-92](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts#L53-L92), [packages/next/src/shared/lib/magic-identifier.ts:123-131](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/magic-identifier.ts#L123-L131)
---
### Step 1: subscribeToClientChanges
The hot reloader maintains active subscription connections to entrypoint endpoints via `subscribeToClientChanges`. When an endpoint detects a file or module change, it yields a stream of `TurbopackResult` updates. The function iterates over these changes, invoking issue processing and message creation callbacks to broadcast HMR payloads to connected browser clients.
Sources: [packages/next/src/server/dev/hot-reloader-turbopack.ts:787-827](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts#L787-L827)
### Step 2: processIssues
As change results flow in, `processIssues` extracts any error, fatal, or warning issues from the result payload and stores them in the `currentEntryIssues` map under the specific entry key. It evaluates severity levels and can trigger immediate module build exceptions or log well-known errors depending on configuration flags.
Sources: [packages/next/src/shared/lib/turbopack/utils.ts:53-92](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts#L53-L92)
### Step 3: formatIssue
`formatIssue` takes a raw `Issue` object and builds a human-readable diagnostic message. It handles file path normalization, source code frame integration, import traces, and maps known issues (such as missing dependencies or Sass requirements) to standard Next.js documentation URLs.
Sources: [packages/next/src/shared/lib/turbopack/utils.ts:101-206](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts#L101-L206)
### Step 4: renderStyledStringToErrorAnsi
Issue titles, descriptions, and details are often represented as `StyledString` trees. `renderStyledStringToErrorAnsi` recursively traverses these structures, transforming text, strong emphasis, and code blocks into ANSI-colored strings suitable for terminal logging and dev overlay rendering, while delegating inner identifier strings for deobfuscation.
Sources: [packages/next/src/shared/lib/turbopack/utils.ts:282-304](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts#L282-L304)
### Step 5: applyDeobfuscation
Nested inside the ANSI renderer, `applyDeobfuscation` passes raw string segments to `deobfuscateText` and post-processes the output by wrapping matched identifier groups in terminal magenta coloring to make compiler symbols easily identifiable.
Sources: [packages/next/src/shared/lib/turbopack/utils.ts:283-288](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts#L283-L288)
### Step 6: deobfuscateText
`deobfuscateText` coordinates text cleaning by invoking `deobfuscateTextParts` to split input strings into raw segments and decoded magic identifiers, stitching the resulting parts back together into a clean, developer-friendly string.
Sources: [packages/next/src/shared/lib/magic-identifier.ts:211-214](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/magic-identifier.ts#L211-L214)
### Step 7: deobfuscateTextParts
`deobfuscateTextParts` scans strings for Turbopack magic identifiers and module metadata. Before matching magic identifiers, it initializes the cleaning pass by stripping away JavaScript runtime noise, such as free call wrappers, and decodes hexadecimal patterns back into readable symbols.
Sources: [packages/next/src/shared/lib/magic-identifier.ts:143-203](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/magic-identifier.ts#L143-L203)
### Step 8: removeFreeCallWrapper
At the foundation of the deobfuscation pipeline, `removeFreeCallWrapper` uses regular expressions to strip out JavaScript comma-operator function-calling boilerplate like `(0, __TURBOPACK__...__.method)`. This eliminates implementation clutter from stack traces and compiler outputs, leaving clean member expressions for error display.
Sources: [packages/next/src/shared/lib/magic-identifier.ts:123-131](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/magic-identifier.ts#L123-L131)
---
## Execution Flow Diagram
```mermaid
sequenceDiagram
participant HotReloader as hot-reloader-turbopack.ts
participant Utils as turbopack/utils.ts
participant MagicID as magic-identifier.ts
HotReloader->>HotReloader: subscribeToClientChanges()
HotReloader->>Utils: processIssues(currentEntryIssues, key, change)
Utils->>Utils: formatIssue(issue)
Utils->>Utils: renderStyledStringToErrorAnsi(title)
Utils->>Utils: applyDeobfuscation(str)
Utils->>MagicID: deobfuscateText(str)
MagicID->>MagicID: deobfuscateTextParts(text)
MagicID->>MagicID: removeFreeCallWrapper(text)
MagicID-->>Utils: Return cleaned/deobfuscated text parts
Utils-->>HotReloader: Return formatted issue / message
HotReloader->>HotReloader: sendHmr(key, message)
```
Sources: [packages/next/src/server/dev/hot-reloader-turbopack.ts:787-827](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts#L787-L827), [packages/next/src/shared/lib/turbopack/utils.ts:53-304](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts#L53-L304), [packages/next/src/shared/lib/magic-identifier.ts:123-214](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/magic-identifier.ts#L123-L214)
---
## Decision Flow
```mermaid
flowchart TD
Sub[subscribeToClientChanges] --> Proc[processIssues]
Proc --> HasIssues{Has Errors?}
HasIssues -- Yes --> Format[formatIssue]
HasIssues -- No --> Skip[Skip / Next Change]
Format --> Render[renderStyledStringToErrorAnsi]
Render --> DeobApp[applyDeobfuscation]
DeobApp --> DeobText[deobfuscateText]
DeobText --> DeobParts[deobfuscateTextParts]
DeobParts --> RmWrapper[removeFreeCallWrapper]
RmWrapper --> Send[Send HMR Message]
```
Sources: [packages/next/src/server/dev/hot-reloader-turbopack.ts:787-827](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts#L787-L827), [packages/next/src/shared/lib/turbopack/utils.ts:53-304](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/utils.ts#L53-L304), [packages/next/src/shared/lib/magic-identifier.ts:123-214](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/magic-identifier.ts#L123-L131)
---
## Key Observations
- **Cross-Module Boundaries:** The execution path traverses from server-side Hot Module Replacement management (`hot-reloader-turbopack.ts`) into shared diagnostic formatting utilities (`turbopack/utils.ts`), and finally deep into string manipulation and identifier decoding logic (`magic-identifier.ts`).
- **Error Resilience:** `subscribeToClientChanges` wraps asynchronous generator consumption in `try/catch` blocks. If an iteration error occurs, the subscription is deleted and optional error payloads are sent to clients.
- **Noise Reduction:** The lower layers (`removeFreeCallWrapper` and `deobfuscateModuleId`) strip compiler-generated artifacts (such as `[app-rsc]`, `(ecmascript)`, and free-call wrappers) so that developers see concise, intuitive source references in their terminals and dev overlays.
---
## Technical docs: Quick Start
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/getting-started/quick-start
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/create-next-app/index.ts](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts)
- [packages/create-next-app/templates/index.ts](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts)
- [packages/next/src/bin/next.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/bin/next.ts)
- [packages/create-next-app/create-app.ts](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts)
- [packages/next/taskfile.js](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js)
- [packages/create-next-app/templates/default/js/pages/index.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default/js/pages/index.js)
- [run-evals.js](https://github.com/blade47/next.js/blob/main/run-evals.js)
- [packages/create-next-app/templates/default-tw/js/pages/index.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw/js/pages/index.js)
- [package.json](https://github.com/blade47/next.js/blob/main/package.json)
- [packages/create-next-app/helpers/examples.ts](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts)
- [packages/next-codemod/bin/next-codemod.ts](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/next-codemod.ts)
- [packages/create-next-app/templates/app/js/app/page.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app/js/app/page.js)
- [packages/create-next-app/templates/default-empty/js/pages/index.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-empty/js/pages/index.js)
- [packages/create-next-app/templates/default-tw-empty/js/pages/index.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw-empty/js/pages/index.js)
- [packages/create-next-app/templates/app-empty/js/app/page.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-empty/js/app/page.js)
- [packages/create-next-app/templates/app-tw/js/app/page.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-tw/js/app/page.js)
- [packages/create-next-app/templates/default/ts/pages/index.tsx](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default/ts/pages/index.tsx)
- [run-tests.js](https://github.com/blade47/next.js/blob/main/run-tests.js)
- [packages/create-next-app/templates/app-tw-empty/js/app/page.js](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-tw-empty/js/app/page.js)
- [packages/next/src/cli/next-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts)
- [packages/next/package.json](https://github.com/blade47/next.js/blob/main/packages/next/package.json)
- [packages/next/app.js](https://github.com/blade47/next.js/blob/main/packages/next/app.js)
- [packages/create-next-app/templates/default-tw/ts/pages/index.tsx](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw/ts/pages/index.tsx)
- [packages/create-next-app/package.json](https://github.com/blade47/next.js/blob/main/packages/create-next-app/package.json)
- [packages/create-next-app/templates/default-empty/ts/pages/index.tsx](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-empty/ts/pages/index.tsx)
- [packages/create-next-app/templates/app/ts/app/page.tsx](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app/ts/app/page.tsx)
- [packages/create-next-app/templates/default-tw-empty/ts/pages/index.tsx](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw-empty/ts/pages/index.tsx)
- [packages/next/src/client/next-dev.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts)
- [packages/next/src/cli/next-dev.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts)
## Overview
Next.js provides a robust command-line interface and tooling ecosystem designed to streamline project initialization, template configuration, development server bootstrapping, and diagnostic inspection. This infrastructure addresses common friction points during application setup by automating directory scaffolding, fetching remote examples, validating runtime environments, and orchestrating build and test workflows across various architectural and styling preferences.
Sources: [packages/create-next-app/index.ts:41-114](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L41-L114), [packages/create-next-app/create-app.ts:28-66](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L28-L66), [packages/next/src/bin/next.ts:138-155](https://github.com/blade47/next.js/blob/main/packages/next/src/bin/next.ts#L138-L155), [packages/next/src/cli/next-dev.ts:45-63](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L45-L63), [packages/next/src/cli/next-info.ts:270-329](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L270-L329)
## CLI Scaffolding Entry Points
### CLI Scaffolding Entry Points
The `create-next-app` package initiates execution through a Node.js shebang header (`#!/usr/bin/env node`) located at the root of `packages/create-next-app/index.ts`. It registers process signal listeners (`SIGINT` and `SIGTERM`) executing `handleSigTerm` to immediately terminate the process upon interruption.
Sources: [packages/create-next-app/index.ts:1-26](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L1-L26)
### Prompt State Management and Lifecycle
User interactions via the `prompts` library are managed through `onPromptState`. If a user aborts prompt entry (`state.aborted`), the state handler explicitly restores the terminal cursor by writing escape codes (`\x1B[?25h`), prints a newline, and exits with code `1`.
Sources: [packages/create-next-app/index.ts:27-39](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L27-L39)
> [!WARNING]
> Abruptly terminating prompts without restoring the terminal state leaves the cursor hidden. The `onPromptState` function specifically writes `\x1B[?25h` to prevent terminal lockups on cancellation.
>
> Sources: [packages/create-next-app/index.ts:27-39](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L27-L39)
### Commander CLI Flag Configuration
The command-line parser relies on `commander` instantiated with `packageJson.name`. It accepts an optional `[directory]` positional argument and supports a comprehensive flag matrix for project customization.
| Option Flag | Type / Argument | Description | Sources |
| :--- | :--- | :--- | :--- |
| `-v, --version` | None | Output the current version of `create-next-app`. | [packages/create-next-app/index.ts:42-46](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L42-L46) |
| `-h, --help` | None | Display help message. | [packages/create-next-app/index.ts:49-49](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L49-L49) |
| `--ts, --typescript` | None | Initialize as a TypeScript project. (default) | [packages/create-next-app/index.ts:50-50](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L50-L50) |
| `--js, --javascript` | None | Initialize as a JavaScript project. | [packages/create-next-app/index.ts:51-51](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L51-L51) |
| `--tailwind` | None | Initialize with Tailwind CSS config. (default) | [packages/create-next-app/index.ts:52-52](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L52-L52) |
| `--react-compiler` | None | Initialize with React Compiler enabled. | [packages/create-next-app/index.ts:53-53](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L53-L53) |
| `--eslint` | None | Initialize with ESLint config. | [packages/create-next-app/index.ts:54-54](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L54-L54) |
| `--biome` | None | Initialize with Biome config. | [packages/create-next-app/index.ts:55-55](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L55-L55) |
| `--app` | None | Initialize as an App Router project. | [packages/create-next-app/index.ts:56-56](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L56-L56) |
| `--src-dir` | None | Initialize inside a `src/` directory. | [packages/create-next-app/index.ts:57-57](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L57-L57) |
| `--rspack` | None | Enable Rspack as the bundler. | [packages/create-next-app/index.ts:58-58](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L58-L58) |
| `--import-alias` | `refix/*>` | Specify import alias to use (default `@/*`). | [packages/create-next-app/index.ts:59-62](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L59-L62) |
| `--api` | None | Initialize a headless API using the App Router. | [packages/create-next-app/index.ts:63-63](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L63-L63) |
| `--empty` | None | Initialize an empty project. | [packages/create-next-app/index.ts:64-64](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L64-L64) |
| `--use-npm` | None | Bootstrap the application using npm. | [packages/create-next-app/index.ts:66-68](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L66-L68) |
| `--use-pnpm` | None | Bootstrap the application using pnpm. | [packages/create-next-app/index.ts:69-72](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L69-L72) |
| `--use-yarn` | None | Bootstrap the application using Yarn. | [packages/create-next-app/index.ts:73-76](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L73-L76) |
| `--use-bun` | None | Bootstrap the application using Bun. | [packages/create-next-app/index.ts:77-80](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L77-L80) |
| `--reset, --reset-preferences` | None | Reset saved preferences for `create-next-app`. | [packages/create-next-app/index.ts:81-84](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L81-L84) |
| `--skip-install` | None | Skip installing packages. | [packages/create-next-app/index.ts:85-88](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L85-L88) |
| `--yes` | None | Use saved preferences or defaults for unprovided options. | [packages/create-next-app/index.ts:89-89](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L89-L89) |
| `-e, --example` | `` | Bootstrap with an official example or public GitHub URL. | [packages/create-next-app/index.ts:90-98](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L90-L98) |
| `--example-path` | `ath-to-example>` | Specify subdirectory path for complex GitHub examples. | [packages/create-next-app/index.ts:99-108](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L99-L108) |
| `--agents-md` | None | Include AGENTS.md for coding agents. (default) | [packages/create-next-app/index.ts:109-112](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L109-L112) |
| `--disable-git` | None | Skip initializing a git repository. | [packages/create-next-app/index.ts:113-113](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L113-L113) |
Sources: [packages/create-next-app/index.ts:41-113](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L41-L113)
### Argument Parsing and Package Manager Resolution
Commander action handlers parse the positional argument, screening out negated options (`--no-`) which can inadvertently pass into the name argument due to parser constraints. Package manager resolution evaluates explicit CLI options in order (`--use-npm`, `--use-pnpm`, `--use-yarn`, `--use-bun`) or falls back to `getPkgManager()`.
Sources: [packages/create-next-app/index.ts:114-137](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L114-L137)
| Design Choice | Benefit | Cost | Sources |
| :--- | :--- | :--- | :--- |
| Explicit flag overrides (`--use-npm`, etc.) | Direct control over package runner without environment detection heuristics | Verbose CLI surface area requiring maintenance for each runner | [packages/create-next-app/index.ts:66-80](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L66-L80), [packages/create-next-app/index.ts:128-136](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L128-L136) |
| Negated option filtering via `!name.startsWith('--no-')` | Prevents parser misinterpretation of boolean flag toggles as project directory paths | Requires manual string inspection inside action handlers | [packages/create-next-app/index.ts:115-121](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L115-L121) |
| Persistent preferences via `Conf` | Remembers user configuration defaults across executions | Requires disk I/O and state clearance handling (`--reset`) | [packages/create-next-app/index.ts:5-5](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L5-L5), [packages/create-next-app/index.ts:81-84](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L81-L84), [packages/create-next-app/index.ts:139-139](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L139-L139) |
Sources: [packages/create-next-app/index.ts:5-5](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L5-L5), [packages/create-next-app/index.ts:66-84](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L66-L84), [packages/create-next-app/index.ts:115-139](https://github.com/blade47/next.js/blob/main/packages/create-next-app/index.ts#L115-L139)
## Project Generation and Example Extraction
### Overview
The project generation and example extraction workflow coordinates filesystem validation, target directory creation, remote GitHub repository or example tarball streaming, and dependency installation. Driven by the `createApp` function, this subsystem takes the parsed configuration options from the CLI entry point, verifies write permissions and folder emptiness, and delegates to helper utilities to pull template or example sources.
Sources: [packages/create-next-app/create-app.ts:28-66](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L28-L66)
### Application Generation Workflow
The main generation entry point follows a strict call-chain execution walkthrough to validate and construct the project workspace:
`createApp()` → `isWriteable()` → `mkdirSync()` → `isFolderEmpty()` → `getRepoInfo()` / `hasRepo()` / `existsInRepo()` → `downloadAndExtractRepo()` / `downloadAndExtractExample()` → `install()`
1. **Validation and Environment Checks**: `createApp` normalizes the root path using `resolve(appPath)` and checks directory writability via `isWriteable(dirname(root))` [packages/create-next-app/create-app.ts:134-136](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L134-L136). If the parent directory is not writeable, it exits with an error [packages/create-next-app/create-app.ts:136-144](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L136-L144).
2. **Directory Initialization**: Creates the target folder recursively via `mkdirSync(root, { recursive: true })` and inspects whether the folder is empty using `isFolderEmpty(root, appName)` [packages/create-next-app/create-app.ts:148-151](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L148-L151).
3. **Example and Repository Resolution**: If an `--example` flag is provided, `createApp` parses the value as a URL or a built-in example name [packages/create-next-app/create-app.ts:71-83](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L71-L83). When a GitHub URL is supplied, `getRepoInfo` extracts the username, repository name, branch, and file path [packages/create-next-app/helpers/examples.ts:23-62](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L23-L62), followed by `hasRepo()` to verify `package.json` existence via GitHub contents API HEAD requests [packages/create-next-app/create-app.ts:106-115](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L106-L115), [packages/create-next-app/helpers/examples.ts:64-74](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L64-L74). For non-URL example names, `existsInRepo()` verifies availability against `vercel/next.js` examples [packages/create-next-app/helpers/examples.ts:76-87](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L76-L87).
4. **Archive Download and Extraction**: Process changes directory to `root` via `process.chdir(root)` [packages/create-next-app/create-app.ts:160-160](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L160-L160). Depending on whether a custom repo or standard example was specified, `downloadAndExtractRepo` or `downloadAndExtractExample` fetches the tarball stream from `codeload.github.com` and pipes it through the `tar` package extractor (`x`) with up to 3 retries via `async-retry` [packages/create-next-app/create-app.ts:178-191](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L178-L191).
5. **Post-Extraction Asset Copying and Installation**: Copies missing `.gitignore` template files and `next-env.d.ts` for TypeScript projects [packages/create-next-app/create-app.ts:204-220](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L204-L220). If `skipInstall` is false and `package.json` exists, `install(packageManager, isOnline)` runs package installation [packages/create-next-app/create-app.ts:222-227](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L222-L227).
Sources: [packages/create-next-app/create-app.ts:71-227](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L71-L227), [packages/create-next-app/helpers/examples.ts:23-87](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L23-L87), [packages/create-next-app/helpers/examples.ts:99-147](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L99-L147)
> [!NOTE]
> During tarball extraction via `downloadAndExtractRepo`, the helper dynamically determines `rootPath` from the first segment of the POSIX-converted paths inside the archive (`pathSegments[0]`). This avoids breaking the file filter if a GitHub repository has been renamed while the fetch URL was redirected.
Sources: [packages/create-next-app/helpers/examples.ts:111-127](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L111-L127)
### Remote Repository and Example Helper Functions
The example and repository helper module (`packages/create-next-app/helpers/examples.ts`) exports core utilities for fetching and validating remote templates over HTTP.
| Function Name | Parameters | Return Type | Purpose | Sources |
| :--- | :--- | :--- | :--- | :--- |
| `isUrlOk` | `url: string` | `Promise` | Checks if a URL responds with HTTP status 200 via a `HEAD` request. | [packages/create-next-app/helpers/examples.ts:14-21](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L14-L21) |
| `getRepoInfo` | `url: URL, examplePath?: string` | `Promise` | Parses GitHub repository path segments to extract username, repo name, branch, and file path. | [packages/create-next-app/helpers/examples.ts:23-62](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L23-L62) |
| `hasRepo` | `RepoInfo` | `Promise` | Validates existence of `package.json` in a remote GitHub repository branch using the contents API. | [packages/create-next-app/helpers/examples.ts:64-74](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L64-L74) |
| `existsInRepo` | `nameOrUrl: string` | `Promise` | Verifies if an example exists within `vercel/next.js` examples or via direct URL check. | [packages/create-next-app/helpers/examples.ts:76-87](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L76-L87) |
| `downloadAndExtractRepo` | `root: string, RepoInfo` | `Promise` | Downloads tarball from `codeload.github.com` and extracts target subdirectory contents into `root`. | [packages/create-next-app/helpers/examples.ts:99-130](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L99-L130) |
| `downloadAndExtractExample` | `root: string, name: string` | `Promise` | Downloads the official `vercel/next.js` canary tarball and extracts the specified example folder. | [packages/create-next-app/helpers/examples.ts:132-147](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L132-L147) |
Sources: [packages/create-next-app/helpers/examples.ts:14-147](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L14-L147)
### Design Trade-Offs
| Design Choice | Benefit | Cost | Sources |
| :--- | :--- | :--- | :--- |
| Streaming Tarball Extraction via `node:stream/promises` (`pipeline`) | Avoids writing large archive files to disk; processes archives on the fly | Requires careful filter mapping for Windows vs POSIX path separators | [packages/create-next-app/helpers/examples.ts:4-4](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L4-L4), [packages/create-next-app/helpers/examples.ts:89-147](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L89-L147) |
| Automatic retry wrapper (`async-retry` with 3 retries) | Resiliency against intermittent network blips during remote tarball downloads | Increases total latency when downloading from dead or unresponsive endpoints | [packages/create-next-app/create-app.ts:2-2](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L2-L2), [packages/create-next-app/create-app.ts:178-181](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L178-L181), [packages/create-next-app/create-app.ts:188-190](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L188-L190) |
| Dynamic `rootPath` detection from tar stream | Handles renamed GitHub repositories seamlessly without breaking extraction filters | Adds runtime introspection logic inside the tar filter callback | [packages/create-next-app/helpers/examples.ts:115-122](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L115-L122) |
Sources: [packages/create-next-app/create-app.ts:2-2](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L2-L2), [packages/create-next-app/create-app.ts:178-190](https://github.com/blade47/next.js/blob/main/packages/create-next-app/create-app.ts#L178-L190), [packages/create-next-app/helpers/examples.ts:4-4](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L4-L4), [packages/create-next-app/helpers/examples.ts:89-147](https://github.com/blade47/next.js/blob/main/packages/create-next-app/helpers/examples.ts#L89-L147)
## Starter Template Matrix and Layouts
### Overview
The `create-next-app` package provides structured starter templates that span different routing architectures, languages, and styling engines. The installation routine defined in `packages/create-next-app/templates/index.ts` handles copying these templates, writing configuration overrides for bundlers like Rspack, configuring the React Compiler, rewriting TypeScript or JavaScript path aliases (`@/*`), and organizing files into an optional `src/` directory.
Sources: [packages/create-next-app/templates/index.ts:48-211](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L48-L211)
### Template Layout Matrix
The project templates provide permutations across the App Router and Pages Router, JavaScript and TypeScript, and Tailwind CSS variants alongside empty starter setups.
| Template / Layout Identifier | Router Architecture | Primary Entry File (JS) | Primary Entry File (TS) | Styling & Font Configuration | Sources |
| :--- | :--- | :--- | :--- | :--- | :--- |
| `default` | Pages Router | `pages/index.js` | `pages/index.tsx` | CSS Modules (`Home.module.css`), Google Fonts (`Geist`, `Geist_Mono`) | [packages/create-next-app/templates/default/js/pages/index.js:1-88](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default/js/pages/index.js#L1-L88), [packages/create-next-app/templates/default/ts/pages/index.tsx:1-89](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default/ts/pages/index.tsx#L1-L89) |
| `default-tw` | Pages Router | `pages/index.js` | `pages/index.tsx` | Tailwind CSS utility classes, Google Fonts (`Geist`, `Geist_Mono`) | [packages/create-next-app/templates/default-tw/js/pages/index.js:1-78](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw/js/pages/index.js#L1-L78), [packages/create-next-app/templates/default-tw/ts/pages/index.tsx:1-79](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw/ts/pages/index.tsx#L1-L79) |
| `default-empty` | Pages Router | `pages/index.js` | `pages/index.tsx` | Minimal Head and basic `Hello world!` markup | [packages/create-next-app/templates/default-empty/js/pages/index.js:1-16](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-empty/js/pages/index.js#L1-L16), [packages/create-next-app/templates/default-empty/ts/pages/index.tsx:1-16](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-empty/ts/pages/index.tsx#L1-L16) |
| `default-tw-empty` | Pages Router | `pages/index.js` | `pages/index.tsx` | Minimal Head with Tailwind / basic markup | [packages/create-next-app/templates/default-tw-empty/js/pages/index.js:1-16](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw-empty/js/pages/index.js#L1-L16), [packages/create-next-app/templates/default-tw-empty/ts/pages/index.tsx:1-16](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw-empty/ts/pages/index.tsx#L1-L16) |
| `app` | App Router | `app/page.js` | `app/page.tsx` | CSS Modules (`page.module.css`), Next/Image assets | [packages/create-next-app/templates/app/js/app/page.js:1-66](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app/js/app/page.js#L1-L66), [packages/create-next-app/templates/app/ts/app/page.tsx:1-66](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app/ts/app/page.tsx#L1-L66) |
| `app-tw` | App Router | `app/page.js` | `app/page.tsx` | Tailwind CSS utility layout, Next/Image assets | [packages/create-next-app/templates/app-tw/js/app/page.js:1-65](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-tw/js/app/page.js#L1-L65) |
| `app-empty` | App Router | `app/page.js` | `app/page.tsx` | Minimal `Hello World!` main element | [packages/create-next-app/templates/app-empty/js/app/page.js:1-7](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-empty/js/app/page.js#L1-L7) |
| `app-tw-empty` | App Router | `app/page.js` | `app/page.tsx` | Minimal `Hello world!` main element | [packages/create-next-app/templates/app-tw-empty/js/app/page.js:1-7](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-tw-empty/js/app/page.js#L1-L7) |
Sources: [packages/create-next-app/templates/index.ts:43-110](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L43-L110), [packages/create-next-app/templates/default/js/pages/index.js:1-88](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default/js/pages/index.js#L1-L88), [packages/create-next-app/templates/default-tw/js/pages/index.js:1-78](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-tw/js/pages/index.js#L1-L78), [packages/create-next-app/templates/app/js/app/page.js:1-66](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app/js/app/page.js#L1-L66), [packages/create-next-app/templates/default-empty/js/pages/index.js:1-16](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default-empty/js/pages/index.js#L1-L16), [packages/create-next-app/templates/app-empty/js/app/page.js:1-7](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-empty/js/app/page.js#L1-L7), [packages/create-next-app/templates/app-tw/js/app/page.js:1-65](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-tw/js/app/page.js#L1-L65), [packages/create-next-app/templates/default/ts/pages/index.tsx:1-89](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/default/ts/pages/index.tsx#L1-L89), [packages/create-next-app/templates/app-tw-empty/js/app/page.js:1-7](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app-tw-empty/js/app/page.js#L1-L7), [packages/create-next-app/templates/app/ts/app/page.tsx:1-66](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/app/ts/app/page.tsx#L1-L66)
### Template Installation and Directory Structuring Walkthrough
When installing a template, `installTemplate` executes an ordered sequence of file operations and configuration updates:
1. `copy()` — Copies matching glob patterns (`**`) from `packages/create-next-app/templates/[template]/[mode]` into `root`, omitting disabled config files (`!eslint.config.mjs`, `!biome.json`, `!postcss.config.mjs`) and renaming `gitignore` to `.gitignore` and `README-template.md` to `README.md`.
2. Bundler injection (`bundler === Bundler.Rspack`) — Reads `next.config.mjs` or `next.config.ts` and wraps `export default nextConfig;` with `withRspack(nextConfig)`.
3. React Compiler injection (`reactCompiler`) — Inserts `reactCompiler: true,` under `/* config options here */` in the Next config file.
4. Path alias configuration — Updates `tsconfig.json` or `jsconfig.json` compiler options to map path aliases (`@/*` or custom `importAlias`) to `./src/*` if `srcDir` is enabled.
5. `src/` migration (`srcDir`) — Creates the `src` directory via `fs.mkdir` and moves the standard directory names (`app`, `pages`, `styles` defined in `SRC_DIR_NAMES`) into `src/`, subsequently updating entry file references in `src/app/page` or `src/pages/index`.
Sources: [packages/create-next-app/templates/index.ts:43-211](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L43-L211)
> [!NOTE]
> During template installation, `SRC_DIR_NAMES` explicitly restricts source directory relocation to `app`, `pages`, and `styles`. Any other top-level files or folders in the template remain at the project root.
>
> Sources: [packages/create-next-app/templates/index.ts:43-43](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L43-L43), [packages/create-next-app/templates/index.ts:179-191](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L179-L191)
### Design Trade-Offs
| Design Choice | Benefit | Cost | Sources |
| :--- | :--- | :--- | :--- |
| Conditional exclusion globbing (`!eslint.config.mjs`, `!postcss.config.mjs`) | Prevents unselected linters or CSS tooling config files from polluting generated directories | Requires explicit negation filters for every optional configuration file in the copier call | [packages/create-next-app/templates/index.ts:72-76](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L72-L76) |
| Post-copy text string replacement for Rspack and React Compiler | Avoids heavy Abstract Syntax Tree (AST) parsing dependencies when modifying configuration files | Fragile against custom formatting or non-standard exports in generated configuration files | [packages/create-next-app/templates/index.ts:97-125](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L97-L125) |
| Concurrency-controlled file rewriting via `Sema(8)` for custom import aliases | Prevents EMFILE file descriptor exhaustion errors on large repository trees | Adds synchronization overhead when traversing and rewriting project files | [packages/create-next-app/templates/index.ts:142-177](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L142-L177) |
Sources: [packages/create-next-app/templates/index.ts:72-76](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L72-L76), [packages/create-next-app/templates/index.ts:97-125](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L97-L125), [packages/create-next-app/templates/index.ts:142-177](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L142-L177)
## Development Server Startup Flow
### Overview
The development server startup flow orchestrates the lifecycle from the initial Next.js binary invocation through environmental preflight validation, forked server child process creation, and client runtime bootstrapping.
Sources: [packages/next/src/bin/next.ts:1-120](https://github.com/blade47/next.js/blob/main/packages/next/src/bin/next.ts#L1-L120), [packages/next/src/cli/next-dev.ts:204-521](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L204-L521), [packages/next/src/client/next-dev.ts:1-25](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts#L1-L25)
### Binary Invocation and Preflight Validation Walkthrough
When executing the Next.js CLI binary, execution proceeds through an explicit validation and hooking pipeline:
1. `require('../server/require-hook')` — Registers runtime module resolution hooks before importing core utilities.
2. Node Version Check — Validates `process.versions.node` against `process.env.__NEXT_REQUIRED_NODE_VERSION_RANGE` using `semver.satisfies`; exits with code `1` if unsupported.
3. Dependency Verification — Resolves `react` and `react-dom` via `require.resolve()`, emitting console warnings if missing from project dependencies.
4. `NextRootCommand.createCommand()` preAction Hook — Sets `NODE_ENV` (defaulting to `'development'` for `dev` and `'production'` otherwise), enforces standard environment checks, pins `process.env.NEXT_RUNTIME = 'nodejs'`, and checks for Apple Silicon Rosetta 2 translation mismatches.
5. `nextDev()` execution (`packages/next/src/cli/next-dev.ts`) — Parses bundler arguments via `parseBundlerArgs`, resolves the project directory via `getProjectDir()`, verifies project directory existence via `fileExists()`, and performs dependency preflight checks.
Sources: [packages/next/src/bin/next.ts:3-116](https://github.com/blade47/next.js/blob/main/packages/next/src/bin/next.ts#L3-L116), [packages/next/src/cli/next-dev.ts:211-262](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L211-L262)
> [!WARNING]
> If a project contains both `sass` and `node-sass` installed concurrently, the preflight checker emits a warning recommending removal of `node-sass`. Additionally, if `@next/font` is detected in dependencies, a migration warning advising migration to built-in `next/font` is triggered.
>
> Sources: [packages/next/src/cli/next-dev.ts:231-260](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L231-L260)
### Dev Server Initialization and Child Process Forking
The `nextDev` function initializes configuration options, inspect addresses, and memory thresholds before spawning the background worker process:
```typescript
child = fork(startServerPath, {
stdio: 'inherit',
execArgv,
env: {
...defaultEnv,
...(isTurbopack ? { TURBOPACK: process.env.TURBOPACK } : undefined),
__NEXT_DEV_SERVER: '1',
NEXT_PRIVATE_START_TIME: process.env.NEXT_PRIVATE_START_TIME,
NEXT_PRIVATE_WORKER: '1',
NEXT_PRIVATE_TRACE_ID: traceId,
NEXT_PRIVATE_ENABLED_FEATURES: JSON.stringify(enabledFeatures),
NEXT_PRIVATE_DEV_SPAN_ATTRS: JSON.stringify(devSpanAttrs),
NODE_OPTIONS: formattedNodeOptions,
WATCHPACK_WATCHER_LIMIT:
os.platform() === 'darwin' ? '20' : undefined,
},
})
```
Sources: [packages/next/src/cli/next-dev.ts:394-427](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L394-L427)
| Configuration Option | Default Source / Fallback | Purpose | Sources |
| :--- | :--- | :--- | :--- |
| `max-old-space-size` | 50% of total system memory (`os.totalmem()`) | Overrides Node.js heap limit unless `NEXT_DISABLE_MEM_OVERRIDE` is set | [packages/next/src/cli/next-dev.ts:355-365](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L355-L365) |
| `WATCHPACK_WATCHER_LIMIT` | `'20'` on macOS (`darwin`), undefined elsewhere | Mitigates Node.js file watcher performance degradation on macOS | [packages/next/src/cli/next-dev.ts:413-414](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L413-L414) |
| `__NEXT_DEV_SERVER` | `'1'` | Signals to the child process that it runs under development server mode | [packages/next/src/cli/next-dev.ts:400-400](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L400-L400) |
| `NEXT_PRIVATE_WORKER` | `'1'` | Identifies the child process as an isolated worker instance | [packages/next/src/cli/next-dev.ts:402-402](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L402-L402) |
Sources: [packages/next/src/cli/next-dev.ts:355-365](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L355-L365), [packages/next/src/cli/next-dev.ts:400-414](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-dev.ts#L400-L414)
### Client Runtime Bootstrapping
Once the development server compiles and serves client assets, the browser runtime bootstraps by initializing the development hot module replacement client and mounting window bindings:
```typescript
import './register-deployment-id-global'
import './webpack'
import { initialize, version, router, emitter } from './'
import initHMR from './dev/hot-middleware-client'
import { pageBootstrap } from './page-bootstrap'
window.next = {
version,
get router() {
return router
},
emitter,
}
const devClient = initHMR()
initialize({ devClient })
.then(({ assetPrefix }) => {
return pageBootstrap(assetPrefix)
})
.catch((err) => {
console.error('Error was not caught', err)
})
```
Sources: [packages/next/src/client/next-dev.ts:1-25](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts#L1-L25)
> [!NOTE]
> `window.next.router` is defined using a getter property to maintain live bindings since the router instance is initialized asynchronously after client module evaluation.
>
> Sources: [packages/next/src/client/next-dev.ts:8-15](https://github.com/blade47/next.js/blob/main/packages/next/src/client/next-dev.ts#L8-L15)
## Environment Diagnostics and Version Inspection
### Overview
Next.js provides built-in environment diagnostics and version inspection capabilities through diagnostic command-line utilities and codemod tooling. The system inspects host system details, compiler bindings, binary dependencies, and package configurations to diagnose runtime environment health.
Sources: [packages/next/src/cli/next-info.ts:254-330](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L254-L330), [packages/next-codemod/bin/next-codemod.ts:1-25](https://github.com/blade47/next-codemod/bin/next-codemod.ts#L1-L25)
### Host System and Installation Diagnostics
The verbose diagnostics routine evaluates platform compatibility, checking for `win32`, `linux`, or `darwin` platforms. It queries system wrappers to report Windows Subsystem for Linux (WSL) status, Docker containerization, continuous integration (CI) environment presence, binary toolchain versions, and relevant package versions.
Sources: [packages/next/src/cli/next-info.ts:254-330](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L254-L330)
| Diagnostic Category | Checked Metric | Source / Implementation Detail | Sources |
| :--- | :--- | :--- | :--- |
| Host System | WSL, Docker, CI | `isWsl`, `isDocker()`, `ciInfo.isCI` | [packages/next/src/cli/next-info.ts:282-292](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L282-L292) |
| Binaries | Node, npm, Yarn, pnpm | `process.versions.node`, binary path execution | [packages/next/src/cli/next-info.ts:310-313](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L310-L313) |
| Relevant Packages | next, eslint-config-next, react, react-dom, typescript | `getPackageVersion()` utility lookup | [packages/next/src/cli/next-info.ts:315-319](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L315-L319) |
| Configuration | output configuration | `nextConfig.output` property | [packages/next/src/cli/next-info.ts:321-321](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L321-L321) |
Sources: [packages/next/src/cli/next-info.ts:282-321](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L282-L321)
> [!NOTE]
> Node.js diagnostic reports are automatically retrieved via `process.report?.getReport()`. Sensitive fields including `cwd`, `commandLine`, `host`, `cpus`, and `networkInterfaces` are explicitly deleted prior to output rendering to prevent leaking host secrets.
>
> Sources: [packages/next/src/cli/next-info.ts:335-352](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L335-L352)
### SWC Binding Verification and Fallback Resolution
Verification of `next-swc` inspects compiled native binaries by loading bindings and querying the target architecture triple.
Sources: [packages/next/src/cli/next-info.ts:367-387](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L367-L387)
The inspection call-chain executes as follows:
`loadBindings()` → retrieves WASM binary preference from `nextConfig.experimental?.useWasmBinary` → evaluates `bindings.getTargetTriple()` → verifies successful target string return to confirm native binding integrity.
Sources: [packages/next/src/cli/next-info.ts:374-386](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L374-L386)
If primary loading fails, the diagnostic tool iterates through platform architecture triples using `@napi-rs/triples`, verifying optional dependencies and fallback directories:
Sources: [packages/next/src/cli/next-info.ts:392-411](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L392-L411)
```typescript
for (const triple of triples) {
const triplePkgName = `@next/swc-${triple.platformArchABI}`
if (tryResolve(triplePkgName)) {
break
}
if (!fallbackBindingsDirectory) {
continue
}
tryResolve(path.join(fallbackBindingsDirectory, triplePkgName))
```
Sources: [packages/next/src/cli/next-info.ts:446-459](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L446-L459)
> [!CAUTION]
> If all target triples fail resolution and fallback checks, `next-swc` diagnostics report a failure state, indicating that native compilation acceleration is unavailable on the host architecture.
>
> Sources: [packages/next/src/cli/next-info.ts:396-401](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.
## Related
- [[System Overview]]
- [[CLI Commands]]
---
## Technical docs: Project Structure
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/getting-started/project-structure
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/package.json](https://github.com/blade47/next.js/blob/main/packages/next/package.json)
- [packages/next/taskfile.js](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js)
- [package.json](https://github.com/blade47/next.js/blob/main/package.json)
- [packages/next/types/$$compiled.internal.d.ts](https://github.com/blade47/next.js/blob/main/packages/next/types/%24%24compiled.internal.d.ts)
- [packages/next/constants.js](https://github.com/blade47/next.js/blob/main/packages/next/constants.js)
- [packages/next/types.js](https://github.com/blade47/next.js/blob/main/packages/next/types.js)
- [packages/next/src/bundles/webpack/packages/package.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/package.js)
- [packages/next/turbo.json](https://github.com/blade47/next.js/blob/main/packages/next/turbo.json)
- [packages/next/document.js](https://github.com/blade47/next.js/blob/main/packages/next/document.js)
- [packages/next/app.js](https://github.com/blade47/next.js/blob/main/packages/next/app.js)
- [packages/next/constants.d.ts](https://github.com/blade47/next.js/blob/main/packages/next/constants.d.ts)
- [packages/next/src/bundles/webpack/packages/sources.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/sources.js)
- [packages/next/src/api/server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts)
- [packages/next/script.js](https://github.com/blade47/next.js/blob/main/packages/next/script.js)
- [packages/next/client.js](https://github.com/blade47/next.js/blob/main/packages/next/client.js)
- [packages/next/navigation.js](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js)
- [packages/next/jest.js](https://github.com/blade47/next.js/blob/main/packages/next/jest.js)
- [packages/next-codemod/package.json](https://github.com/blade47/next.js/blob/main/packages/next-codemod/package.json)
- [packages/next/tsconfig.json](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.json)
- [packages/next/src/server/after/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts)
- [packages/next/index.d.ts](https://github.com/blade47/next.js/blob/main/packages/next/index.d.ts)
- [packages/next/src/next-devtools/entrypoint.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/entrypoint.ts)
- [packages/next/src/api/constants.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/constants.ts)
- [packages/next/tsconfig.build.json](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.build.json)
- [packages/next/src/api/navigation.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts)
- [packages/next/types.d.ts](https://github.com/blade47/next.js/blob/main/packages/next/types.d.ts)
- [pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml)
- [turbo.json](https://github.com/blade47/next.js/blob/main/turbo.json)
## Overview
The repository follows a structured monorepo topology orchestrated via pnpm workspaces and Turborepo task pipelines, establishing clear boundaries between core packages, applications, benchmarks, and native build crates. Sources: [package.json:4-7](https://github.com/blade47/next.js/blob/main/package.json#L4-L7), [pnpm-workspace.yaml:1-8](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L1-L8), [turbo.json:1-35](https://github.com/blade47/next.js/blob/main/turbo.json#L1-L35). Within the primary `next` package, functionality is organized into specialized internal subsystems, compiled vendor dependencies, and root-level module resolution facades that expose clean entry points for clients, servers, navigation, and testing while maintaining isolated compilation and build targets. Sources: [packages/next/package.json:5-82](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L5-L82), [packages/next/taskfile.js:1450-1568](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1450-L1568).
## Workspace and Monorepo Organization
### Overview
The repository's workspace topology is rooted at the top-level manifest and governed by `pnpm-workspace.yaml`, which outlines the exact package patterns included in the build graph. The included patterns encompass `apps/*`, `packages/*`, `bench/*`, `crates/*/js`, `turbopack/crates/*/js`, `turbopack/crates/turbopack-tests/tests/execution`, and `turbopack/packages/*`. Sources: [pnpm-workspace.yaml:1-8](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L1-L8). Root package configurations also declare `workspaces` pointing to `"packages/*"`. Sources: [package.json:4-7](https://github.com/blade47/next.js/blob/main/package.json#L4-L7). Security and dependency hoisting are governed by `publicHoistPattern` containing `*eslint*`, allowed builds for `@ast-grep/cli`, and a `minimumReleaseAge` of `2880` minutes (48 hours) with specific exclusions for scopes such as `@next/*`, `@turbo/*`, `@vercel/*`, `@workflow/*`, `babel-plugin-react-compiler`, `next`, `react`, `react-dom`, `react-is`, `react-server-dom-*`, `scheduler`, and `turbo`. Sources: [pnpm-workspace.yaml:10-49](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L10-L49).
### Turborepo Task Pipelines
Task orchestration is defined at the root via `turbo.json`, establishing global execution parameters, environment variables, and task dependency graphs. Global environment variables passed to tasks include `CI` and `NEXT_CI_RUNNER`, while `RUSTC_WRAPPER` and `SCCACHE_*` are passed through. Sources: [turbo.json:1-4](https://github.com/blade47/next.js/blob/main/turbo.json#L1-L4). The Turborepo configuration utilizes the terminal user interface (`"ui": "tui"`). Sources: [turbo.json:34](https://github.com/blade47/next.js/blob/main/turbo.json#L34).
| Task Name | Dependencies (`dependsOn`) | Inputs | Outputs / Environment | Purpose |
| :--- | :--- | :--- | :--- | :--- |
| `build` | `[^build]` | — | `dist/**` | Package compilation task referencing upstream workspace dependencies. Sources: [turbo.json:5-9](https://github.com/blade47/next.js/blob/main/turbo.json#L5-L9). |
| `dev` | `[^dev]` | — | `dist/**` | Development watch/serve task across workspace packages. Sources: [turbo.json:10-13](https://github.com/blade47/next.js/blob/main/turbo.json#L10-L13). |
| `storybook` | — | — | — | Storybook execution task. Sources: [turbo.json:14](https://github.com/blade47/next.js/blob/main/turbo.json#L14). |
| `build-storybook` | `[^build-storybook]` | — | `storybook-static/**` | Storybook compilation task. Sources: [turbo.json:15-18](https://github.com/blade47/next.js/blob/main/turbo.json#L15-L18). |
| `test-storybook` | `[^test-storybook]` | — | — | Storybook testing task. Sources: [turbo.json:19-21](https://github.com/blade47/next.js/blob/main/turbo.json#L19-L21). |
| `pack-for-isolated-tests` | — | `$TURBO_DEFAULT$, dist/**` | `packed.tgz` | Bundles package artifacts for isolated test runs. Sources: [turbo.json:22-25](https://github.com/blade47/next.js/blob/main/turbo.json#L22-L25). |
| `typescript` | — | — | — | Type checking task. Sources: [turbo.json:26](https://github.com/blade47/next.js/blob/main/turbo.json#L26). |
| `//#typescript` | — | — | — | Root-scoped type checking task. Sources: [turbo.json:27](https://github.com/blade47/next.js/blob/main/turbo.json#L27). |
| `//#get-test-timings` | — | `run-tests.js` | `test-timings.json` (Env: `KV_REST_API_URL`, `KV_REST_API_TOKEN`) | Fetches and records test timing metrics. Sources: [turbo.json:28-32](https://github.com/blade47/next.js/blob/main/turbo.json#L28-L32). |
Sources: [turbo.json:1-35](https://github.com/blade47/next.js/blob/main/turbo.json#L1-L35).
> [!NOTE]
> The sub-package `packages/next/turbo.json` extends the root workspace configuration (`"extends": ["//"]`) and overrides the `build` task to depend on both `@next/bundle-analyzer-ui#build` and `^build`, outputting to `dist/**`. Sources: [packages/next/turbo.json:1-10](https://github.com/blade47/next.js/blob/main/packages/next/turbo.json#L1-L10).
### Monorepo Scripts and Execution Workflow
Root scripts defined in `package.json` invoke Turborepo tasks, Lerna commands, and script runners to manage testing, linting, and building. For instance, package cleaning is executed via `lerna clean -y && lerna run clean && lerna exec 'node ../../scripts/rm.mjs dist'`. Sources: [package.json:11](https://github.com/blade47/next.js/blob/main/package.json#L11). Production builds run `turbo run build --remote-cache-timeout 60 --summarize true`, while extended builds execute `turbo run build build-native-auto --remote-cache-timeout 60 --summarize true`. Sources: [package.json:12-13](https://github.com/blade47/next.js/blob/main/package.json#L12-L13).
> [!IMPORTANT]
> When executing development environments or testing suites across multiple bundlers (such as Webpack, Rspack, and Turbopack), scripts leverage `scripts/run-jest.sh` with specific flags like `--mode=dev`, `--bundler=webpack`, and `--headless`. Sources: [package.json:22-29](https://github.com/blade47/next.js/blob/main/package.json#L22-L29).
Sources: [package.json:1-91](https://github.com/blade47/next.js/blob/main/package.json#L1-L91).
## Core Next Package Configuration
### Overview
The core `next` package configuration governs the structure, build mechanics, and type declarations of the Next.js framework package located in `packages/next`. It integrates package manifests (`package.json`), TypeScript compiler options (`tsconfig.json`, `tsconfig.build.json`), taskrunner integration via Taskr, and an extensive set of top-level type definition entry points (`index.d.ts`, `types.d.ts`). Sources: [packages/next/package.json:1-102](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L1-L102), [packages/next/tsconfig.json:1-50](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.json#L1-L50), [packages/next/tsconfig.build.json:1-24](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.build.json#L1-L24), [packages/next/index.d.ts:1-20](https://github.com/blade47/next.js/blob/main/packages/next/index.d.ts#L1-L20).
### Package Manifest and Dependencies
The `packages/next/package.json` file establishes the identity of the package as `"name": "next"` with version `"16.3.0-canary.51"`, setting its main entry point to `./dist/server/next.js`, binary executable mapping for `next` under `./dist/bin/next`, and type declarations root pointing to `index.d.ts`. Sources: [packages/next/package.json:1-10, 80-82](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L1-L10,_L80-L82).
Runtime dependencies and peer dependencies control compilation requirements and external framework compatibility.
| Dependency Type | Name / Identifier | Version / Range | Purpose |
| :--- | :--- | :--- | :--- |
| Dependency | `@next/env` | `16.3.0-canary.51` | Environment variable loading for Next.js. Sources: [packages/next/package.json:104](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L104). |
| Dependency | `@swc/helpers` | `0.5.15` | SWC runtime helper functions. Sources: [packages/next/package.json:105](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L105). |
| Dependency | `baseline-browser-mapping` | `^2.9.19` | Baseline browser mapping utility. Sources: [packages/next/package.json:106](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L106). |
| Dependency | `caniuse-lite` | `^1.0.30001579` | Browser feature support database. Sources: [packages/next/package.json:107](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L107). |
| Dependency | `postcss` | `8.5.10` | CSS transformations and styling pipelines. Sources: [packages/next/package.json:108](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L108). |
| Dependency | `styled-jsx` | `5.1.6` | Component-scoped CSS styling. Sources: [packages/next/package.json:109](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L109). |
| Peer Dependency | `@opentelemetry/api` | `^1.1.0` | Telemetry instrumentation tracing. Sources: [packages/next/package.json:112](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L112). |
| Peer Dependency | `@playwright/test` | `^1.51.1` | End-to-end testing support. Sources: [packages/next/package.json:113](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L113). |
| Peer Dependency | `babel-plugin-react-compiler` | `*` | React compiler optimization plugin. Sources: [packages/next/package.json:114](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L114). |
| Peer Dependency | `react` | `^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0` | React core library peer requirement. Sources: [packages/next/package.json:115](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L115). |
| Peer Dependency | `react-dom` | `^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0` | React DOM rendering peer requirement. Sources: [packages/next/package.json:116](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L116). |
| Peer Dependency | `sass` | `^1.3.0` | Sass CSS preprocessor support. Sources: [packages/next/package.json:117](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L117). |
Sources: [packages/next/package.json:103-118](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L103-L118).
Package scripts configure local development (`dev`: `cross-env NEXT_SERVER_NO_MANGLE=1 taskr`), production compilation (`build`: `taskr release`), and type generation (`types`: `tsc --project tsconfig.build.json --declaration --emitDeclarationOnly --stripInternal --declarationDir dist`). Sources: [packages/next/package.json:83-87](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L83-L87). The `taskr` property specifies taskfile requirements including `./taskfile-webpack.js`, `./taskfile-ncc.js`, `./taskfile-swc.js`, and `./taskfile-watch.js`. Sources: [packages/next/package.json:95-101](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L95-L101).
Sources: [packages/next/package.json:83-102](https://github.com/blade47/next.js/blob/main/packages/next/package.json#L83-L102).
### TypeScript Configuration and Build Options
TypeScript options are structured across `tsconfig.json` extending `../../tsconfig-tsec.json` and `tsconfig.build.json` extending `tsconfig.json`. Sources: [packages/next/tsconfig.json:1-3](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.json#L1-L3), [packages/next/tsconfig.build.json:1-2](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.build.json#L1-L2). The compiler options enforce strictness and module bundling guidelines.
| Compiler Option | Value | Purpose |
| :--- | :--- | :--- |
| `strict` | `true` | Enables all strict type-checking options. Sources: [packages/next/tsconfig.json:4](https://github.com/blade47/next.js/blob/main/tsconfig.json#L4). |
| `stripInternal` | `true` | Omits declarations marked with `@internal` from emitted output. Sources: [packages/next/tsconfig.json:5](https://github.com/blade47/next.js/blob/main/tsconfig.json#L5). |
| `esModuleInterop` | `true` | Enables interoperability between CommonJS and ES Modules. Sources: [packages/next/tsconfig.json:6](https://github.com/blade47/next.js/blob/main/tsconfig.json#L6). |
| `verbatimModuleSyntax` | `true` | Preserves type-only imports and exports without transformation. Sources: [packages/next/tsconfig.json:7](https://github.com/blade47/next.js/blob/main/tsconfig.json#L7). |
| `jsx` | `react-jsx` | Emits JSX transformed with React 17+ fragment/element factories. Sources: [packages/next/tsconfig.json:8](https://github.com/blade47/next.js/blob/main/tsconfig.json#L8). |
| `module` | `ESNext` | Specifies ECMAScript module target generation. Sources: [packages/next/tsconfig.json:9](https://github.com/blade47/next.js/blob/main/tsconfig.json#L9). |
| `target` | `ES2018` | Sets JavaScript language target version. Sources: [packages/next/tsconfig.json:10](https://github.com/blade47/next.js/blob/main/tsconfig.json#L10). |
| `moduleResolution` | `bundler` | Resolves modules using bundler-style resolution rules. Sources: [packages/next/tsconfig.json:11](https://github.com/blade47/next.js/blob/main/tsconfig.json#L11). |
| `types` | `["trusted-types", "jest", "node"]` | Specifies global type packages included during compilation. Sources: [packages/next/tsconfig.json:12](https://github.com/blade47/next.js/blob/main/tsconfig.json#L12). |
Sources: [packages/next/tsconfig.json:4-12](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.json#L4-L12).
The configuration maps absolute paths to prevent circular overwriting errors during `tsc` execution and enables auto-completion before builds. Mapped paths include `next/dist/client/app-find-source-map-url`, `next/dist/client/app-call-server`, `next/dist/compiled/@edge-runtime/ponyfill`, `next/dist/compiled/@vercel/og/satori`, and `next/dist/shared/lib/image-loader`. Sources: [packages/next/tsconfig.json:13-34](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.json#L13-L34).
> [!WARNING]
> `tsconfig.json` explicitly excludes output directories and legacy declaration files (`./dist/**/*`, `./*.d.ts`, `future/*.d.ts`, `image-types/global.d.ts`, `compat/*.d.ts`, `legacy/*.d.ts`, `types/compiled.d.ts`, `navigation-types/*.d.ts`, `navigation-types/compat/*.d.ts`, `experimental/**/*.d.ts`) to avoid input file overwrite conflicts. Sources: [packages/next/tsconfig.json:38-49](https://github.com/blade47/next.js/blob/main/tsconfig.json#L38-L49). Furthermore, `tsconfig.build.json` defines `"rootDir": "src"` and excludes test and storybook files (`./**/*.test.ts`, `./**/*.test.tsx`, `./**/*.stories.tsx`, `./**/storybook/**/*`) to prevent generating declarations for internal test code. Sources: [packages/next/tsconfig.build.json:1-24](https://github.com/blade47/next.js/blob/main/packages/next/tsconfig.build.json#L1-L24).
### Top-Level Type Declarations
Top-level type definitions are orchestrated by `packages/next/index.d.ts`, which references global types, compiled types, styled-jsx types, and core subsystem declaration files before exporting module types. Sources: [packages/next/index.d.ts:1-20](https://github.com/blade47/next.js/blob/main/packages/next/index.d.ts#L1-L20).
```typescript
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
export { default } from './types'
export * from './types'
```
Sources: [packages/next/index.d.ts:1-20](https://github.com/blade47/next.js/blob/main/packages/next/index.d.ts#L1-L20).
The bridge file `packages/next/types.d.ts` directly exports all declarations originating from `./dist/types`, connecting the source declaration outputs to the package consumer interface. Sources: [packages/next/types.d.ts:1-3](https://github.com/blade47/next.js/blob/main/packages/next/types.d.ts#L1-L3).
## Root Module Resolution Facades
### Overview
The `packages/next/` directory provides top-level proxy files that act as resolution facades, forwarding CommonJS `module.exports` and TypeScript type definitions directly to their compiled counterparts inside the `./dist/` directory. These entry points decouple public consumer imports (such as `next/navigation`, `next/client`, or `next/script`) from internal folder layouts and build artifacts. Sources: [packages/next/constants.js:1](https://github.com/blade47/next.js/blob/main/packages/next/constants.js#L1), [packages/next/navigation.js:1](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1).
### Facade Module Mapping
Each top-level JavaScript facade delegates runtime execution to specific compilation outputs within the `dist` folder tree. Similarly, type declaration facades such as `packages/next/constants.d.ts` use ambient wildcard or direct module exports to expose types from the build output. Sources: [packages/next/constants.js:1](https://github.com/blade47/next.js/blob/main/packages/next/constants.js#L1), [packages/next/constants.d.ts:1](https://github.com/blade47/next.js/blob/main/packages/next/constants.d.ts#L1).
| Facade Entry Point | Resolution Target | Exported Domain | Sources |
| :--- | :--- | :--- | :--- |
| `packages/next/constants.js` | `./dist/shared/lib/constants` | Shared application constants | Sources: [packages/next/constants.js:1](https://github.com/blade47/next.js/blob/main/packages/next/constants.js#L1) |
| `packages/next/constants.d.ts` | `./dist/shared/lib/constants` | Shared constant type definitions | Sources: [packages/next/constants.d.ts:1](https://github.com/blade47/next.js/blob/main/packages/next/constants.d.ts#L1) |
| `packages/next/document.js` | `./dist/pages/_document` | Pages router document template | Sources: [packages/next/document.js:1](https://github.com/blade47/next.js/blob/main/packages/next/document.js#L1) |
| `packages/next/app.js` | `./dist/pages/_app` | Pages router application root | Sources: [packages/next/app.js:1](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1) |
| `packages/next/script.js` | `./dist/client/script` | Client-side script optimization component | Sources: [packages/next/script.js:1](https://github.com/blade47/next.js/blob/main/packages/next/script.js#L1) |
| `packages/next/client.js` | `./dist/client/index` | Client-side runtime entry | Sources: [packages/next/client.js:1](https://github.com/blade47/next.js/blob/main/packages/next/client.js#L1) |
| `packages/next/navigation.js` | `./dist/client/components/navigation` | App router navigation hooks | Sources: [packages/next/navigation.js:1](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1) |
| `packages/next/jest.js` | `./dist/build/jest/jest` | Jest testing integration presets | Sources: [packages/next/jest.js:1](https://github.com/blade47/next.js/blob/main/packages/next/jest.js#L1) |
Sources: [packages/next/constants.js:1](https://github.com/blade47/next.js/blob/main/packages/next/constants.js#L1), [packages/next/constants.d.ts:1](https://github.com/blade47/next.js/blob/main/packages/next/constants.d.ts#L1), [packages/next/document.js:1](https://github.com/blade47/next.js/blob/main/packages/next/document.js#L1), [packages/next/app.js:1](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1), [packages/next/script.js:1](https://github.com/blade47/next.js/blob/main/packages/next/script.js#L1), [packages/next/client.js:1](https://github.com/blade47/next.js/blob/main/packages/next/client.js#L1), [packages/next/navigation.js:1](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1), [packages/next/jest.js:1](https://github.com/blade47/next.js/blob/main/packages/next/jest.js#L1).
### Runtime Facade Implementation
The implementation across all runtime facades relies on synchronous CommonJS `require` calls pointing to compiled distribution targets. For instance, navigation features load directly from the client components bundle, while document and app templates load from the pages build output. Sources: [packages/next/app.js:1](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1), [packages/next/navigation.js:1](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1).
```javascript
module.exports = require('./dist/pages/_app')
```
Sources: [packages/next/app.js:1](https://github.com/blade47/next.js/blob/main/packages/next/app.js#L1)
```javascript
module.exports = require('./dist/client/components/navigation')
```
Sources: [packages/next/navigation.js:1](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1)
```javascript
module.exports = require('./dist/build/jest/jest')
```
Sources: [packages/next/jest.js:1](https://github.com/blade47/next.js/blob/main/packages/next/jest.js#L1)
> [!NOTE]
> Resolution facades like `packages/next/navigation.js` and `packages/next/jest.js` decouple consumers from internal build directory structures, allowing the compiler output organization under `./dist/` to change without breaking external import paths like `next/navigation` or `next/jest`. Sources: [packages/next/navigation.js:1](https://github.com/blade47/next.js/blob/main/packages/next/navigation.js#L1), [packages/next/jest.js:1](https://github.com/blade47/next.js/blob/main/packages/next/jest.js#L1).
## Internal Subsystems and API Architecture
### Overview
The codebase organizes its internal API architecture and subsystems under the `packages/next/src/` directory, exposing structured re-exports across server handlers, asynchronous lifecycle hooks, navigation primitives, shared constants, and development tools. These internal modules bridge package-level entry points to specific internal compilation domains. Sources: [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2), [packages/next/src/api/constants.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/constants.ts#L1-L2), [packages/next/src/api/navigation.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts#L1-L2), [packages/next/src/server/after/index.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts#L1-L2), [packages/next/src/next-devtools/entrypoint.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/entrypoint.ts#L1-L2).
### Internal Subsystem Modules
The API architecture maps internal directory modules directly to domain-specific source trees via wildcard re-exports. Server-side web APIs delegate through `packages/next/src/api/server.ts` to web export handlers, while navigation functions route through `packages/next/src/api/navigation.ts` to client navigation components. Sources: [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2), [packages/next/src/api/navigation.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts#L1-L2).
| Internal API Module | Delegation Target | Subsystem Domain | Sources |
| :--- | :--- | :--- | :--- |
| `packages/next/src/api/server.ts` | `../server/web/exports/index` | Server web runtime exports | Sources: [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2) |
| `packages/next/src/api/constants.ts` | `../shared/lib/constants` | Shared application constants | Sources: [packages/next/src/api/constants.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/constants.ts#L1-L2) |
| `packages/next/src/api/navigation.ts` | `../client/components/navigation` | Client navigation components | Sources: [packages/next/src/api/navigation.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts#L1-L2) |
| `packages/next/src/server/after/index.ts` | `./after` | Asynchronous task deferral handlers | Sources: [packages/next/src/server/after/index.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts#L1-L2) |
| `packages/next/src/next-devtools/entrypoint.ts` | `./dev-overlay.browser` | Browser development overlay | Sources: [packages/next/src/next-devtools/entrypoint.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/entrypoint.ts#L1-L2) |
Sources: [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2), [packages/next/src/api/constants.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/constants.ts#L1-L2), [packages/next/src/api/navigation.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/navigation.ts#L1-L2), [packages/next/src/server/after/index.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts#L1-L2), [packages/next/src/next-devtools/entrypoint.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/entrypoint.ts#L1-L2).
### Facade Delegation Syntax
Internal subsystem entry points utilize wildcard export declarations (`export * from ...`) to aggregate and expose subsystem implementations without hardcoding individual function signatures. Sources: [packages/next/src/api/server.ts:1](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1), [packages/next/src/server/after/index.ts:1](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts#L1), [packages/next/src/next-devtools/entrypoint.ts:1](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/entrypoint.ts#L1).
```typescript
export * from '../server/web/exports/index'
```
Sources: [packages/next/src/api/server.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/api/server.ts#L1-L2)
```typescript
export * from './after'
```
Sources: [packages/next/src/server/after/index.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts#L1-L2)
```typescript
export * from './dev-overlay.browser'
```
Sources: [packages/next/src/next-devtools/entrypoint.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/entrypoint.ts#L1-L2)
> [!NOTE]
> Devtools entrypoints bind directly to browser-specific overlay targets (`./dev-overlay.browser`), isolating development UI elements from production server bundles. Sources: [packages/next/src/next-devtools/entrypoint.ts:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/entrypoint.ts#L1-L2).
## Compilation Targets and Bundled Dependencies
### Overview
Next.js manages third-party dependencies and compilation outputs through automated Taskfile build routines and dedicated internal bundle shims. Vendor packages such as PostCSS utilities, React runtimes, and webpack sources are compiled, bundled, or aliased into `src/compiled/` to isolate them from external module resolution conflicts and Haste module map warnings. Sources: [packages/next/taskfile.js:1431-1446](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1431-L1446), [packages/next/taskfile.js:1450-1477](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1450-L1477).
### Taskfile Build and NCC Compilation Targets
The Taskfile build pipeline invokes `ncc` compilation routines to bundle external libraries into internal distribution targets. For instance, `ncc_icss_utils` resolves `icss-utils`, marks `postcss/lib/parser` as external, and outputs the bundled result directly to `src/compiled/icss-utils`. Sources: [packages/next/taskfile.js:1435-1446](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1435-L1446).
```javascript
export async function ncc_icss_utils(task, opts) {
await task
.source(relative(__dirname, require.resolve('icss-utils')))
.ncc({
packageName: 'icss-utils',
externals: {
'postcss/lib/parser': 'postcss/lib/parser',
...externals,
},
})
.target('src/compiled/icss-utils')
}
```
Sources: [packages/next/taskfile.js:1435-1446](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1435-L1446)
### Vendor React and Scheduler Copy Execution Walkthrough
The `copy_vendor_react` task processes experimental and standard React channels through a multi-step transformation sequence.
1. **Channel and Suffix Resolution:** `copy_vendor_react_impl` inspects `opts.experimental` to determine the channel (`experimental-builtin` or `builtin`) and package suffix (`-experimental` or ``). Sources: [packages/next/taskfile.js:1451-1453](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1451-L1453).
2. **Package Name Rewriting:** `overridePackageName` parses `package.json` files and appends the channel suffix to `json.name` if absent, ensuring Haste module map warnings are avoided. Sources: [packages/next/taskfile.js:1458-1464](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1458-L1464).
3. **Module Aliasing:** `aliasVendoredReactPackages` replaces string occurrences of `require("react")`, `require("react-dom")`, and `require("scheduler")` inside CommonJS chunks with their `next/dist/compiled/` equivalents containing the appropriate package suffix. Sources: [packages/next/taskfile.js:1479-1493](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1479-L1493).
4. **AST Parsing and Modification:** `parseFile` utilizes `recast` with an Acorn parser configured for `latest` ECMAScript versions and script source types, enabling AST traversal and identifier replacement via `replaceIdentifiersInAst`. Sources: [packages/next/taskfile.js:1570-1605](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1570-L1605).
Sources: [packages/next/taskfile.js:1450-1605](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1450-L1605).
> [!WARNING]
> React DOM CJS files undergo package aliasing but must preserve server-rendering stub mappings, preventing blanket replacement of `react-dom` references with internal compiled paths in contexts where stubs are active. Sources: [packages/next/taskfile.js:1556-1568](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1556-L1568).
### Internal Bundle Shims and Type Declarations
Internal module resolution relies on type declaration shims located in `packages/next/types/$$compiled.internal.d.ts` alongside webpack facade wrappers. These files map `next/dist/compiled/*` module paths directly to upstream dependency exports or custom wrapper modules. Sources: [packages/next/types/$$compiled.internal.d.ts:487-502](https://github.com/blade47/next.js/blob/main/packages/next/types/%24%24compiled.internal.d.ts#L487-L502), [packages/next/src/bundles/webpack/packages/package.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/package.js#L1-L2).
| Module Shim / Facade Path | Target Resolution | Purpose | Sources |
| :--- | :--- | :--- | :--- |
| `next/dist/compiled/commander` | `commander` | CLI argument parser module shim | Sources: [packages/next/types/$$compiled.internal.d.ts:487-489](https://github.com/blade47/next.js/blob/main/packages/next/types/%24%24compiled.internal.d.ts#L487-L489) |
| `next/dist/compiled/jest-worker` | `jest-worker` | Worker process farm module shim | Sources: [packages/next/types/$$compiled.internal.d.ts:499-501](https://github.com/blade47/next.js/blob/main/packages/next/types/%24%24compiled.internal.d.ts#L499-L501) |
| `packages/next/src/bundles/webpack/packages/package.js` | `./webpack.js`.package | Webpack package bundle entry facade | Sources: [packages/next/src/bundles/webpack/packages/package.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/package.js#L1-L2) |
| `packages/next/src/bundles/webpack/packages/sources.js` | `./webpack.js`.sources | Webpack sources bundle entry facade | Sources: [packages/next/src/bundles/webpack/packages/sources.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/sources.js#L1-L2) |
Sources: [packages/next/types/$$compiled.internal.d.ts:487-502](https://github.com/blade47/next.js/blob/main/packages/next/types/%24%24compiled.internal.d.ts#L487-L502), [packages/next/src/bundles/webpack/packages/package.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/package.js#L1-L2), [packages/next/src/bundles/webpack/packages/sources.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/sources.js#L1-L2).
> [!TIP]
> Webpack internal bundling delegates specialized exports like `package` and `sources` through local proxy files into a central `webpack.js` module core, maintaining a clean separation of bundle entry points. Sources: [packages/next/src/bundles/webpack/packages/package.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/package.js#L1-L2), [packages/next/src/bundles/webpack/packages/sources.js:1-2](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/sources.js#L1-L2).
## Related
- [[System Overview]]
- [[Monorepo Workspace]]
---
## Technical docs: Monorepo Workspace
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/getting-started/monorepo-workspace
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next-codemod/lib/agents-md.ts](https://github.com/blade47/next.js/blob/main/packages/next-codemod/lib/agents-md.ts)
- [packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml)
- [packages/next-codemod/bin/__testfixtures__/geo-ip-usage/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/geo-ip-usage/pnpm-workspace.yaml)
- [packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/pnpm-workspace.yaml)
- [package.json](https://github.com/blade47/next.js/blob/main/package.json)
- [packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/pnpm-workspace.yaml)
- [pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml)
- [packages/next/src/cli/next-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts)
- [packages/next/src/cli/internal/static-routes-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts)
- [packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-app-router/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-app-router/pnpm-workspace.yaml)
- [packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-app-router/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-app-router/pnpm-workspace.yaml)
- [packages/next-codemod/bin/__testfixtures__/react-18-installed-mixed-router/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-18-installed-mixed-router/pnpm-workspace.yaml)
- [lerna.json](https://github.com/blade47/next.js/blob/main/lerna.json)
- [packages/next-codemod/bin/__testfixtures__/react-19-installed-mixed-router/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-19-installed-mixed-router/pnpm-workspace.yaml)
- [conductor.json](https://github.com/blade47/next.js/blob/main/conductor.json)
- [packages/next/taskfile.js](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js)
- [packages/next-codemod/bin/__testfixtures__/suggest-turbopack/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/suggest-turbopack/pnpm-workspace.yaml)
- [socket.yaml](https://github.com/blade47/next.js/blob/main/socket.yaml)
- [packages/next-codemod/bin/__testfixtures__/no-geo-ip-usage/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/no-geo-ip-usage/pnpm-workspace.yaml)
- [packages/next-codemod/bin/__testfixtures__/change-turbo-to-turbopack/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/change-turbo-to-turbopack/pnpm-workspace.yaml)
- [packages/next-codemod/bin/__testfixtures__/peer-dep-out-of-range/met-range/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/peer-dep-out-of-range/met-range/pnpm-workspace.yaml)
- [packages/create-next-app/templates/index.ts](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts)
- [packages/next-codemod/bin/__testfixtures__/peer-dep-out-of-range/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/peer-dep-out-of-range/pnpm-workspace.yaml)
- [packages/next/src/lib/find-root.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts)
- [packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml)
- [packages/next/src/server/lib/chrome-devtools-workspace.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/chrome-devtools-workspace.ts)
- [apps/bundle-analyzer/lib/analyze-data.ts](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts)
- [packages/next-codemod/lib/handle-package.ts](https://github.com/blade47/next.js/blob/main/packages/next-codemod/lib/handle-package.ts)
- [turbopack/packages/node-module-trace/package.json](https://github.com/blade47/next.js/blob/main/turbopack/packages/node-module-trace/package.json)
- [packages/next/src/bundles/webpack/packages/package.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/package.js)
## Overview
The Monorepo Workspace provides the foundational architecture for developing, testing, and building Next.js and its associated tooling across multiple integrated packages and standalone applications. It establishes strict workspace configurations, automated build pipelines, and runtime discovery utilities to seamlessly coordinate dependencies across diverse package managers and orchestrators. Sources: [conductor.json:1-4](https://github.com/blade47/next.js/blob/main/conductor.json#L1-L4), [pnpm-workspace.yaml:1-9](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L1-L9)
By enforcing structured package boundaries, deterministic lockfile resolution, and comprehensive diagnostic inspection, the workspace architecture solves complex dependency management and bundling challenges inherent in large-scale JavaScript and Rust-based hybrid repositories. Sources: [packages/next/src/lib/find-root.ts:34-65](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L34-L65), [packages/next/src/cli/internal/static-routes-info.ts:1-16](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L1-L16)
## Monorepo Layout and Workspace Configuration
### Workspace Management Architecture
The root workspace architecture organizes the repository by integrating `pnpm`, `Lerna`, and `Conductor` orchestrations to govern dependency layout, package publishing, and developer environment management. These orchestration layers define precise package globs, publish workflows, environment defaults, and security constraints across the repository. Sources: [pnpm-workspace.yaml:1-9](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L1-L9), [lerna.json:1-19](https://github.com/blade47/next.js/blob/main/lerna.json#L1-L19), [conductor.json:1-14](https://github.com/blade47/next.js/blob/main/conductor.json#L1-L14)
### PNPM Workspace Layout
The `pnpm-workspace.yaml` configuration dictates how workspaces are scanned and resolved across applications, packages, benchmarks, and Turbopack Rust-to-JS bindings. Sources: [pnpm-workspace.yaml:1-8](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L1-L8)
| Package Glob Pattern | Target Component / Subsystem | Sources |
| :--- | :--- | :--- |
| `apps/*` | Standalone applications and consumer examples | [pnpm-workspace.yaml:2-2](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L2-L2) |
| `packages/*` | Core framework packages and shared libraries | [pnpm-workspace.yaml:3-3](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L3-L3) |
| `bench/*` | Performance benchmark suites | [pnpm-workspace.yaml:4-4](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L4-L4) |
| `crates/*/js` | Rust crate JavaScript bindings | [pnpm-workspace.yaml:5-5](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L5-L5) |
| `turbopack/crates/*/js` | Turbopack Rust crate JavaScript bindings | [pnpm-workspace.yaml:6-6](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L6-L6) |
| `turbopack/crates/turbopack-tests/tests/execution` | Turbopack execution test suites | [pnpm-workspace.yaml:7-7](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L7-L7) |
| `turbopack/packages/*` | Turbopack package ecosystem | [pnpm-workspace.yaml:8-8](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L8-L8) |
Sources: [pnpm-workspace.yaml:1-8](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L1-L8)
> [!IMPORTANT]
> The pnpm workspace disables update notifications via `updateNotifier: false` and hoists specific eslint dependencies using `publicHoistPattern: ['*eslint*']` while enforcing security boundaries with `blockExoticSubdeps: true` and a 48-hour minimum release age (`minimumReleaseAge: 2880`). Sources: [pnpm-workspace.yaml:9-11](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L9-L11), [pnpm-workspace.yaml:34-35](https://github.com/blade47/next.js/blob/main/pnpm-workspace.yaml#L34-L35)
### Lerna Versioning and Publishing
Lerna manages multi-package version coordination and publication pipelines at the repository root. It relies on `pnpm` as the underlying `npmClient` and restricts publishing actions to the `canary` branch targeting the public npm registry. Sources: [lerna.json:1-17](https://github.com/blade47/next.js/blob/main/lerna.json#L1-L17)
| Lerna Configuration Property | Value / Scope | Sources |
| :--- | :--- | :--- |
| `npmClient` | `pnpm` | [lerna.json:2-2](https://github.com/blade47/next.js/blob/main/lerna.json#L2-L2) |
| `packages` | `packages/*` | [lerna.json:3-5](https://github.com/blade47/next.js/blob/main/lerna.json#L3-L5) |
| `command.version.exact` | `true` | [lerna.json:7-9](https://github.com/blade47/next.js/blob/main/lerna.json#L7-L9) |
| `command.publish.npmClient` | `npm` | [lerna.json:10-11](https://github.com/blade47/next.js/blob/main/lerna.json#L10-L11) |
| `command.publish.allowBranch` | `["canary"]` | [lerna.json:12-14](https://github.com/blade47/next.js/blob/main/lerna.json#L12-L14) |
| `command.publish.registry` | `https://registry.npmjs.org/` | [lerna.json:15-15](https://github.com/blade47/next.js/blob/main/lerna.json#L15-L15) |
| `version` | `16.3.0-canary.51` | [lerna.json:18-18](https://github.com/blade47/next.js/blob/main/lerna.json#L18-L18) |
Sources: [lerna.json:1-18](https://github.com/blade47/next.js/blob/main/lerna.json#L1-L18)
### Conductor Orchestration and Environment
The Conductor configuration establishes workspace environment defaults, lifecycle scripts, worktree branches, and developer operational recommendations. Sources: [conductor.json:1-23](https://github.com/blade47/next.js/blob/main/conductor.json#L1-L23)
> [!CAUTION]
> Never execute `pnpm build` while `pnpm dev` is active within the workspace, as concurrent builds cause file corruption in Rust artifacts and bundled outputs. Sources: [conductor.json:21-21](https://github.com/blade47/next.js/blob/main/conductor.json#L21-L21)
Sources: [conductor.json:1-24](https://github.com/blade47/next.js/blob/main/conductor.json#L1-L24)
## Workspace Root and Lockfile Discovery
### Overview
Workspace root and lockfile discovery mechanisms locate project boundaries, detect active package managers, and traverse directory trees to establish correct execution and build roots. Sources: [packages/next/src/lib/find-root.ts:5-65](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L5-L65), [packages/next-codemod/lib/handle-package.ts:55-87](https://github.com/blade47/next-codemod/lib/handle-package.ts#L55-L87)
### Workspace Root Discovery and Traversal Algorithm
#### Traversal Mechanics
The runtime discovery process identifies workspace boundaries by searching upward from the current working directory (`cwd`) for workspace configuration files and lockfiles using `find-up`. Sources: [packages/next/src/lib/find-root.ts:5-32](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L5-L32)
#### Call-Chain Execution Walkthrough
The workspace discovery pipeline executes through the following sequence:
1. `findRootDirAndLockFiles(cwd)` initiates root and lockfile gathering. Sources: [packages/next/src/lib/find-root.ts:34-38](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L34-L38)
2. `findWorkRoot(cwd)` runs first, executing an upward search prioritized for `pnpm-workspace.yaml` before checking other lockfile types to prevent accidental inclusion of nested lockfiles. Sources: [packages/next/src/lib/find-root.ts:5-32](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L5-L32)
3. If a lockfile or workspace file is found, `findRootDirAndLockFiles` enters a `while (true)` traversal loop, checking parent directories via `dirname(currentDir)` until reaching the filesystem root (`parentDir === currentDir`) or finding additional parent lockfiles. Sources: [packages/next/src/lib/find-root.ts:46-59](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L46-L59)
4. Finally, `rootDir` is resolved as `dirname(lockFiles[lockFiles.length - 1])`. Sources: [packages/next/src/lib/find-root.ts:63-63](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L63-L63)
> [!NOTE]
> `findWorkRoot` explicitly checks for `pnpm-workspace.yaml` prior to searching for general lockfiles to ensure that root configuration files take precedence over nested application lockfiles. Sources: [packages/next/src/lib/find-root.ts:6-18](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L6-L18)
Sources: [packages/next/src/lib/find-root.ts:5-65](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L5-L65)
### Multi-Manager Detection and Lockfile Handling
Package managers are identified through lockfile inspection or environment variables. The codebase handles multiple package managers and supports duplicate lockfile warnings when nested configurations are detected. Sources: [packages/next-codemod/lib/handle-package.ts:55-87](https://github.com/blade47/next-codemod/lib/handle-package.ts#L55-L87)
| Lockfile / Config Name | Detected Package Manager | Sources |
| :--- | :--- | :--- |
| `package-lock.json` | `npm` | [packages/next-codemod/lib/handle-package.ts:69-70](https://github.com/blade47/next-codemod/lib/handle-package.ts#L69-L70) |
| `yarn.lock` | `yarn` | [packages/next-codemod/lib/handle-package.ts:71-72](https://github.com/blade47/next-codemod/lib/handle-package.ts#L71-L72) |
| `pnpm-lock.yaml` / `pnpm-workspace.yaml` | `pnpm` | [packages/next-codemod/lib/handle-package.ts:73-74](https://github.com/blade47/next-codemod/lib/handle-package.ts#L73-L74), [packages/next/src/lib/find-root.ts:8-14](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L8-L14) |
| `bun.lock` / `bun.lockb` | `bun` | [packages/next-codemod/lib/handle-package.ts:75-77](https://github.com/blade47/next-codemod/lib/handle-package.ts#L75-L77) |
> [!WARNING]
> If multiple lockfiles are detected during traversal (`lockFiles.length > 1`), Next.js emits a warning selecting the topmost lockfile directory as the root and instructing developers to configure `turbopack.root` or `outputFileTracingRoot` to silence the warning. Sources: [packages/next/src/lib/find-root.ts:67-93](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L67-L93)
Sources: [packages/next/src/lib/find-root.ts:34-94](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/find-root.ts#L34-L94), [packages/next-codemod/lib/handle-package.ts:55-87](https://github.com/blade47/next-codemod/lib/handle-package.ts#L55-L87)
## Workspace Packages and Applications Structure
### Overview
The workspace architecture organizes source code across generation templates, analytical standalone applications, and experimental tracing packages. Scaffolding utilities within `packages/create-next-app` configure project templates dynamically, translating user flags into workspace configurations, package manager rules, and dependency structures. Sources: [packages/create-next-app/templates/index.ts:1-435](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts)
### Template Generation and Package Configuration
The template installation process handled by `installTemplate` manages file copying, compiler integration, import alias normalization, and manifest serialization. It maps user-selected bundlers, linters, and package managers directly into `package.json` configurations and workspace files. Sources: [packages/create-next-app/templates/index.ts:48-408](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts)
| Configuration Flag | Target File | Modification Logic | Sources |
| :--- | :--- | :--- | :--- |
| `bundler: Bundler.Rspack` | `next.config.mjs` / `next.config.ts` | Wraps default export with `withRspack(nextConfig)` and injects `next-rspack` dependency | [packages/create-next-app/templates/index.ts:97-110](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L97-L110), [packages/create-next-app/templates/index.ts:258-260](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L258-L260) |
| `reactCompiler: true` | `next.config.mjs` / `next.config.ts` | Inserts `reactCompiler: true` into config options and adds `babel-plugin-react-compiler` | [packages/create-next-app/templates/index.ts:112-125](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L112-L125), [packages/create-next-app/templates/index.ts:262-264](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L262-L264) |
| `importAlias` | `tsconfig.json` / `jsconfig.json` & Source Files | Replaces `@/*` paths with custom alias and recursively updates matching imports across source files | [packages/create-next-app/templates/index.ts:127-177](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L127-L177) |
| `srcDir: true` | Target root directory | Creates `src/` directory, relocates default app directories (`app`, `pages`, `styles`), and updates entry points | [packages/create-next-app/templates/index.ts:179-211](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L179-L211) |
| `packageManager: pnpm` | `pnpm-workspace.yaml` | Writes workspace restriction maps such as `allowBuilds` or `ignoredBuiltDependencies` for packages like `sharp` and `unrs-resolver` | [packages/create-next-app/templates/index.ts:333-376](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L333-L376) |
> [!WARNING]
> When `packageManager` is set to `bun`, the generated manifest automatically populates both `ignoreScripts` and `trustedDependencies` with `sharp` and `unrs-resolver` to suppress installation warnings and satisfy Bun security requirements. Sources: [packages/create-next-app/templates/index.ts:391-402](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L391-L402)
Sources: [packages/create-next-app/templates/index.ts:48-408](https://github.com/blade47/next.js/blob/main/packages/create-next-app/templates/index.ts#L48-L408)
### Bundle Analysis and Binary Data Structures
#### ArrayBuffer Ingestion Architecture
The workspace includes dedicated analysis tools under `apps/bundle-analyzer` designed to ingest structured build outputs from Rust compilers. The parser processes binary chunks and module graphs via `ModulesData` and `AnalyzeData` classes using `DataView` interfaces over raw ArrayBuffers. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:1-203](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L1-L203)
#### Call-Chain Execution Walkthrough
The bundle analysis data-loading sequence proceeds as follows:
1. `new ModulesData(modulesArrayBuffer)` receives the raw binary buffer. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:65-65](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L65-L65)
2. `DataView` extracts a 32-bit big-endian integer representing the JSON header length from offset `0`. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:67-68](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L67-L68)
3. `TextDecoder('utf-8')` decodes the subsequent JSON byte range into the `ModulesDataHeader` schema. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:69-75](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L69-L75)
4. The remaining binary segment starting at `4 + modulesJsonLength` is wrapped into a secondary `DataView` (`modulesBinaryData`) for efficient edge-index lookups without full deserialization. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:76-80](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L76-L80)
5. Finally, `pathToModuleIndex` mapping constructs an index lookup table linking file paths to module indices. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:82-92](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L82-L92)
> [!NOTE]
> Edge relationships such as `moduleDependents`, `asyncModuleDependents`, and `tracedModuleDependents` are read lazily via `readEdgesDataAtIndex` by computing variable-length offset boundaries directly from the binary data view. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:108-198](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L108-L198)
Sources: [apps/bundle-analyzer/lib/analyze-data.ts:60-203](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L60-L203)
### Experimental Node Module Tracing Package
The `turbopack/packages/node-module-trace` package operates as an experimental dependency file tracing utility within the monorepo structure. Publishing under the `@vercel/experimental-nft` package name with alias `node-file-trace`, it exposes metadata configuration specifying public access and MIT licensing rules. Sources: [turbopack/packages/node-module-trace/package.json:1-10](https://github.com/blade47/next.js/blob/main/turbopack/packages/node-module-trace/package.json#L1-L10)
Sources: [turbopack/packages/node-module-trace/package.json:1-10](https://github.com/blade47/next.js/blob/main/turbopack/packages/node-module-trace/package.json#L1-L10)
## Task Automation and Bundle Pipelines
### Overview
Task automation and bundle pipelines within the monorepo rely on programmatic taskfile execution and dedicated precompiled dependency distribution pipelines. Sources: [packages/next/taskfile.js:2752-2795](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2752-L2795)
### Taskfile Execution and Watch Pipelines
#### Watch Initialization
The default taskfile export initializes a development build lifecycle by clearing the `dist` directory, triggering the main `build` task, and registering active file watchers across source subdirectories. Each watcher maps specific source paths to corresponding compilation targets with development options enabled (`opts = { dev: true }`). Sources: [packages/next/taskfile.js:2752-2755](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2752-L2755)
#### Call-Chain Execution Walkthrough
The default watcher registration sequence proceeds as follows:
1. `export default async function (task)` initializes the task context and clears the `dist` target directory via `task.clear('dist')`. Sources: [packages/next/taskfile.js:2752-2754](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2752-L2754)
2. `task.start('build', opts)` executes the initial compilation pipeline. Sources: [packages/next/taskfile.js:2755-2755](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2755-L2755)
3. `task.watch('src/bin', 'bin', opts)` registers incremental rebuild bindings for binary CLI entry points. Sources: [packages/next/taskfile.js:2756-2756](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2756-L2756)
4. `task.watch('src/server', ['server', 'server_esm', 'server_wasm'], opts)` binds server source modifications to CommonJS, ESM, and WebAssembly compilation targets. Sources: [packages/next/taskfile.js:2758-2758](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2758-L2758)
5. `task.watch('src/shared', [...], opts)` dispatches shared module updates across re-exported, ESM, and standard target pipelines. Sources: [packages/next/taskfile.js:2790-2794](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2790-L2794)
> [!NOTE]
> The shared source watcher explicitly excludes test files (`**/*.test.js`, `**/*.test.ts`, `**/*.test.tsx`, `**/*.test.d.ts`) and core configuration modules like `config`, `constants`, `dynamic`, `app-dynamic`, `head`, and `runtime-config`. Sources: [packages/next/taskfile.js:2797-2805](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2797-L2805)
Sources: [packages/next/taskfile.js:2752-2807](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2752-L2807)
### Precompiled Dependency and Vendor Distribution Pipelines
Vendor distribution pipelines manage external packages such as React, React DOM, Scheduler, and PostCSS plugins by copying compiled CommonJS artifacts, rewriting package manifests, and removing redundant distribution files. For instance, `copy_vendor_react` processes experimental or standard channels via `overridePackageName` and `aliasVendoredReactPackages`. Sources: [packages/next/taskfile.js:1435-1493](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1435-L1493)
| Item to Remove | Target Directory | Purpose | Sources |
| :--- | :--- | :--- | :--- |
| `static.js` | `src/compiled/react-dom*` | Removes unused static server entry point | [packages/next/taskfile.js:1620-1626](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1620-L1626) |
| `static.browser.js` | `src/compiled/react-dom*` | Removes browser-specific static rendering artifact | [packages/next/taskfile.js:1620-1626](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1620-L1626) |
| `unstable_testing.js` | `src/compiled/react-dom*` | Strips unstable testing entry point | [packages/next/taskfile.js:1620-1627](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1620-L1627) |
| `test-utils.js` | `src/compiled/react-dom*` | Strips test utility module | [packages/next/taskfile.js:1620-1628](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1620-L1628) |
| `server.bun.js` | `src/compiled/react-dom*` | Removes Bun runtime server bundle | [packages/next/taskfile.js:1620-1629](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1620-L1629) |
| `unstable_server-external-runtime.js` | `src/compiled/react-dom*` | Removes unstable external runtime helper | [packages/next/taskfile.js:1620-1634](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1620-L1634) |
Sources: [packages/next/taskfile.js:1620-1639](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1620-L1639)
> [!WARNING]
> When compiling error codes via `check_error_codes`, failures in CI environments automatically output a notification instructing developers to run `pnpm build` or `pnpm update-error-codes` to synchronize `errors.json` before forcing a process exit with code `1`. Sources: [packages/next/taskfile.js:2733-2750](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2733-L2750)
Sources: [packages/next/taskfile.js:1435-1639](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L1435-L1639), [packages/next/taskfile.js:2733-2750](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js#L2733-L2750)
## Workspace Diagnostics and Route Analytics
### Overview
Monorepo diagnostics and analytics combine command-line inspection utilities, static route measurement, and live Chrome DevTools workspace integration to provide insight into a built application's structure and environment. Sources: [packages/next/src/cli/next-info.ts:1-169](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L1-L169), [packages/next/src/cli/internal/static-routes-info.ts:1-16](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L1-L16)
### Diagnostic Inspection and Environment Reporting
The `next info` CLI utility (`printInfo()`) collects environment parameters, binary versions, and package versions to standard output. Sources: [packages/next/src/cli/next-info.ts:96-169](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L96-L169)
| Package Key | Resolution Source | Fallback / Default | Sources |
| :--- | :--- | :--- | :--- |
| `next` | `getPackageVersion('next')` | `'N/A'` | [packages/next/src/cli/next-info.ts:55-61](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L55-L61), [packages/next/src/cli/next-info.ts:97-97](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L97-L97) |
| `eslint-config-next` | `getPackageVersion('eslint-config-next')` | `'N/A'` | [packages/next/src/cli/next-info.ts:55-61](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L55-L61), [packages/next/src/cli/next-info.ts:137-137](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L137-L137) |
| `react` | `getPackageVersion('react')` | `'N/A'` | [packages/next/src/cli/next-info.ts:55-61](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L55-L61), [packages/next/src/cli/next-info.ts:138-138](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L138-L138) |
| `react-dom` | `getPackageVersion('react-dom')` | `'N/A'` | [packages/next/src/cli/next-info.ts:55-61](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L55-L61), [packages/next/src/cli/next-info.ts:139-139](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L139-L139) |
| `typescript` | `getPackageVersion('typescript')` | `'N/A'` | [packages/next/src/cli/next-info.ts:55-61](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L55-L61), [packages/next/src/cli/next-info.ts:140-140](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L140-L140) |
| `next-rspack` | `getPackageVersion('next-rspack')` (Conditional on `process.env.NEXT_RSPACK`) | `'N/A'` | [packages/next/src/cli/next-info.ts:55-61](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L55-L61), [packages/next/src/cli/next-info.ts:142-145](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L142-L145) |
Sources: [packages/next/src/cli/next-info.ts:55-145](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L55-L145)
> [!WARNING]
> When `printInfo()` checks the package registry for release staleness via `fetch`, network failures do not halt execution. Instead, they emit a yellow-highlighted warning instructing the user to verify against the latest canary release. Sources: [packages/next/src/cli/next-info.ts:105-133](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts#L105-L133)
### Static Route Analysis Pipeline
The `next internal static-routes-info` command performs static bundle size reporting across built routes without executing application code. Sources: [packages/next/src/cli/internal/static-routes-info.ts:1-16](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L1-L16)
| Category Constant | Human-Readable Label | Target File Classification | Sources |
| :--- | :--- | :--- | :--- |
| `clientJs` | Client JS | Client-side JavaScript bundles and chunks | [packages/next/src/cli/internal/static-routes-info.ts:62-62](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L62-L62), [packages/next/src/cli/internal/static-routes-info.ts:73-73](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L73-L73) |
| `clientCss` | Client CSS | Client stylesheets | [packages/next/src/cli/internal/static-routes-info.ts:63-63](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L63-L63), [packages/next/src/cli/internal/static-routes-info.ts:74-74](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L74-L74) |
| `clientMaps` | Client Source Maps | Client-side source map files (.map) | [packages/next/src/cli/internal/static-routes-info.ts:64-64](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L64-L64), [packages/next/src/cli/internal/static-routes-info.ts:75-75](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L75-L75) |
| `serverBundled` | Server Bundled JS | Server-side bundled JavaScript files | [packages/next/src/cli/internal/static-routes-info.ts:65-65](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L65-L65), [packages/next/src/cli/internal/static-routes-info.ts:76-76](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L76-L76) |
| `serverUnbundled` | Server Unbundled | Traced external dependencies (e.g., `node_modules`) | [packages/next/src/cli/internal/static-routes-info.ts:66-66](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L66-L66), [packages/next/src/cli/internal/static-routes-info.ts:77-77](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L77-L77) |
| `serverMaps` | Server Source Maps | Server-side source map files | [packages/next/src/cli/internal/static-routes-info.ts:67-67](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L67-L67), [packages/next/src/cli/internal/static-routes-info.ts:78-78](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L78-L78) |
Sources: [packages/next/src/cli/internal/static-routes-info.ts:61-79](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L61-L79)
> [!TIP]
> Sorting keys available via `--sort` include `name`, `client`, `client-js`, `client-css`, `client-map`, `server`, `server-bundled-js`, `server-unbundled`, `server-map`, and `total`. Sources: [packages/next/src/cli/internal/static-routes-info.ts:36-47](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts#L36-L47)
### Chrome DevTools Workspace Integration
The server exposes an endpoint to support Chrome DevTools Workspaces via `isChromeDevtoolsWorkspaceUrl(pathname)` matching `/.well-known/appspecific/com.chrome.devtools.json`. Sources: [packages/next/src/server/lib/chrome-devtools-workspace.ts:1-31](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/chrome-devtools-workspace.ts#L1-L31)
```typescript
async function getChromeDevtoolsWorkspace(
root: string,
configDistDir: string
): Promise {
if (workspaceUUID === null) {
const distDir = path.join(root, configDistDir)
const cacheBaseDir = getStorageDirectory(distDir)
if (cacheBaseDir === undefined) {
workspaceUUID = randomUUID()
} else {
const cachedUUIDPath = path.join(
cacheBaseDir,
'chrome-devtools-workspace-uuid'
)
try {
workspaceUUID = await fs.promises.readFile(cachedUUIDPath, 'utf8')
} catch {
workspaceUUID = randomUUID()
try {
await fs.promises.writeFile(cachedUUIDPath, workspaceUUID, 'utf8')
} catch (cause) {
console.warn(
new Error(
'Failed to persist Chrome DevTools workspace UUID. The Chrome DevTools Workspace needs to be reconnected after the next page reload.',
{ cause }
)
)
}
}
}
}
return {
workspace: {
uuid: workspaceUUID,
root,
},
}
}
```
Sources: [packages/next/src/server/lib/chrome-devtools-workspace.ts:46-89](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/chrome-devtools-workspace.ts#L46-L89)
> [!IMPORTANT]
> The workspace UUID is held in a module-level variable (`workspaceUUID`) to remain constant throughout the server's lifecycle. Sources: [packages/next/src/server/lib/chrome-devtools-workspace.ts:10-10](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/chrome-devtools-workspace.ts#L10-L10)
## Multi-Workspace Fixtures and Compatibility Matrix
### Fixture System Overview
The test fixtures under `packages/next-codemod/bin/__testfixtures__/` supply a matrix of workspace configurations and compatibility scenarios for validating codemod operations across Next.js versions, React major versions, router structures, and package manager feature sets. Sources: [packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml#L1-L1), [packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml:1-4](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml#L1-L4)
### Compatibility Matrix and Workspace Fixture Catalog
The test suite organizes fixtures into specific categories reflecting dependency setups, feature flags, and package manager options. Sources: [packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml#L1-L1)
| Fixture Path | Focus Area / Scenario | Workspace Configuration | Sources |
|---|---|---|---|
| `packages/next-codemod/bin/__testfixtures__/next-14-installed/` | Next.js version 14 migration baseline | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/geo-ip-usage/` | IP geolocation API usage detection | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/geo-ip-usage/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/geo-ip-usage/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/no-geo-ip-usage/` | Absence of geolocation API usage | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/no-geo-ip-usage/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/no-geo-ip-usage/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/` | React 18 with Pages router exclusively | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/` | React 19 with Pages router exclusively | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-app-router/` | React 18 with App router exclusively | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-app-router/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-app-router/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-app-router/` | React 19 with App router exclusively | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-app-router/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-app-router/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/react-18-installed-mixed-router/` | React 18 with mixed Pages and App routers | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/react-18-installed-mixed-router/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-18-installed-mixed-router/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/react-19-installed-mixed-router/` | React 19 with mixed Pages and App routers | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/react-19-installed-mixed-router/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/react-19-installed-mixed-router/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/suggest-turbopack/` | Turbopack adoption suggestion | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/suggest-turbopack/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/suggest-turbopack/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/change-turbo-to-turbopack/` | CLI flag migration from turbo to turbopack | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/change-turbo-to-turbopack/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/change-turbo-to-turbopack/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/peer-dep-out-of-range/` | Peer dependency mismatch scenarios | Empty workspace root | [packages/next-codemod/bin/__testfixtures__/peer-dep-out-of-range/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/peer-dep-out-of-range/pnpm-workspace.yaml#L1-L1) |
| `packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/` | PNPM v11 build controls and overrides | Explicit `allowBuilds` configuration | [packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml:1-4](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml#L1-L4) |
Sources: [packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml:1-1](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/next-14-installed/pnpm-workspace.yaml#L1-L1), [packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml:1-4](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml#L1-L4)
### PNPM v11 Workspace Build Constraints
The `pnpm-v11-overrides` fixture defines explicit package build permissions via the `allowBuilds` mapping in `pnpm-workspace.yaml`. Sources: [packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml:1-4](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml#L1-L4)
```yaml
allowBuilds:
sharp: false
unrs-resolver: false
```
Sources: [packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml:1-4](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml#L1-L4)
> [!WARNING]
> Setting build permissions to `false` in `allowBuilds` prevents native postinstall compilation scripts from executing for packages such as `sharp` and `unrs-resolver`, which can affect native module loading during workspace test executions. Sources: [packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml:1-4](https://github.com/blade47/next.js/blob/main/packages/next-codemod/bin/__testfixtures__/pnpm-v11-overrides/pnpm-workspace.yaml#L1-L4)
## Related
- [[Project Structure]]
---
## Technical docs: Server Request Lifecycle
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/server-request-lifecycle
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next/src/server/next-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts)
- [packages/next/src/server/lib/router-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-server.ts)
- [packages/next/src/server/app-render/app-render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx)
- [packages/next/src/server/dev/next-dev-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts)
- [packages/next/src/server/next.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts)
- [packages/next/src/server/web/adapter.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/adapter.ts)
- [packages/next/src/server/render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx)
- [packages/next/src/server/base-http/node.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts)
- [packages/next/src/server/base-http/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts)
- [packages/next/src/server/base-http/web.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts)
- [packages/next/src/server/lib/start-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts)
- [packages/next/src/server/request-meta.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts)
- [packages/next/src/server/image-optimizer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts)
- [packages/next/src/server/lib/patch-set-header.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-set-header.ts)
## Overview
The server request lifecycle governs how incoming HTTP connections are received, abstracted, processed, and rendered across different runtime environments. It coordinates server initialization, uniform request/response encapsulation, metadata tracking, routing pipelines, and rendering execution for both the App and Pages routers, while providing robust error handling and development-mode compilation hooks.
Sources: [packages/next/src/server/base-server.ts:1714-1729](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1714-L1729), [packages/next/src/server/base-http/index.ts:28-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L103), [packages/next/src/server/request-meta.ts:51-338](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts#L51-L338), [packages/next/src/server/lib/router-server.ts:371-431](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-server.ts#L371-L431)
## Server Entry and Initialization
### Overview
Incoming HTTP connections are received and initialized through `startServer` or wrapped via `NextServer` and `NextCustomServer` classes. The server establishes network listeners, handles port retries and process cleanups, and delegates incoming socket and request events into router handlers.
Sources: [packages/next/src/server/lib/start-server.ts:184-295](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L184-L295), [packages/next/src/server/next.ts:183-248](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L248)
### Server Initialization and Lifecycle Execution
The startup procedure orchestrates socket binding, worker messaging, and configuration parsing through a deterministic call sequence.
```mermaid
sequenceDiagram
participant CLI as startServer() / Worker
participant HTTP as http.createServer()
participant INIT as getRequestHandlers()
participant ROUTER as initialize()
CLI->>HTTP: Create server with requestListener & upgrade handlers
HTTP->>CLI: server.listen(port, hostname)
CLI->>INIT: Trigger getRequestHandlers() on 'listening' event
INIT->>ROUTER: Call initialize(opts)
ROUTER--YIELD-->CLI: Return requestHandler, upgradeHandler, server
```
Sources: [packages/next/src/server/lib/start-server.ts:139-178](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L139-L178), [packages/next/src/server/lib/start-server.ts:274-321](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L274-L321)
### Server Wrapper Implementations
Next.js provides distinct server wrappers for production execution (`NextServer`), custom server integrations via `import next from 'next'` (`NextCustomServer`), and worker-based process spawning.
| Class / Function | Target Use Case | Key Methods | Sources |
|------------------|-----------------|-------------|---------|
| `NextServer` | `next start` production server wrapper | `getRequestHandler()`, `getServer()`, `prepare()` | [packages/next/src/server/next.ts:183-423](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L423) |
| `NextCustomServer` | Custom servers using `import next from 'next'` | `prepare()`, `getRequestHandler()`, `render()` | [packages/next/src/server/next.ts:425-612](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L425-L612) |
| `startServer` | Standalone server lifecycle runner | `requestListener()`, `server.listen()` | [packages/next/src/server/lib/start-server.ts:184-353](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L184-L353) |
Sources: [packages/next/src/server/next.ts:183-612](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L612), [packages/next/src/server/lib/start-server.ts:184-353](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L184-L353)
> [!NOTE]
> During server initialization in development (`isDev`), `startServer` sets up a `Watchpack` instance monitoring configuration files (`CONFIG_FILES`) and distribution directories (`absDistDir`) to trigger an automatic server restart with `RESTART_EXIT_CODE` upon modifications or deletions.
Sources: [packages/next/src/server/lib/start-server.ts:557-608](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L557-L608)
### Request Dispatched Handlers
When an HTTP connection arrives at `requestListener`, requests await the initialization promise (`handlersPromise`) before being passed to `requestHandler`. Upgrade requests are similarly captured and routed through `upgradeHandler`.
```typescript
async function requestListener(req: IncomingMessage, res: ServerResponse) {
try {
if (handlersPromise) {
await handlersPromise
handlersPromise = undefined
}
await requestHandler(req, res)
} catch (err) {
res.statusCode = 500
res.end('Internal Server Error')
Log.error(`Failed to handle request for ${req.url}`)
console.error(err)
}
}
```
Sources: [packages/next/src/server/lib/start-server.ts:240-272](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L240-L272)
## HTTP Abstraction and Request Adapters
### Overview
Next.js unifies request and response handling across Node.js and Web standard runtime environments through abstract base classes (`BaseNextRequest` and `BaseNextResponse`) implemented by concrete runtime wrappers (`NodeNextRequest`, `NodeNextResponse`, `WebNextRequest`, and `WebNextResponse`). This encapsulation allows server pipelines to interact with request streams, headers, cookies, and status codes uniformly regardless of whether execution occurs in a Node.js server environment or a Web-standard edge sandbox.
Sources: [packages/next/src/server/base-http/index.ts:28-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L103), [packages/next/src/server/base-http/node.ts:19-169](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L19-L169), [packages/next/src/server/base-http/web.ts:11-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L11-L140)
### HTTP Abstraction Architecture
The architecture relies on abstract classes that define common properties and shared utility methods like cookie parsing and redirect helpers, while delegating low-level input/output operations to runtime-specific classes.
| Abstract Class | Concrete Node.js Class | Concrete Web Class | Destination / Underlying Body Type | Sources |
|----------------|------------------------|--------------------|----------------------------------|---------|
| `BaseNextRequest` | `NodeNextRequest` | `WebNextRequest` | Node.js `Readable` stream vs Web `ReadableStream | null` | [packages/next/src/server/base-http/index.ts:28-45](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L45), [packages/next/src/server/base-http/node.ts:19-73](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L19-L73), [packages/next/src/server/base-http/web.ts:11-36](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L11-L36) |
| `BaseNextResponse` | `NodeNextResponse` | `WebNextResponse` | Node.js `Writable` (`ServerResponse`) vs Web `WritableStream` (`TransformStream`) | [packages/next/src/server/base-http/index.ts:47-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L47-L103), [packages/next/src/server/base-http/node.ts:75-169](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L75-L169), [packages/next/src/server/base-http/web.ts:38-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L38-L140) |
Sources: [packages/next/src/server/base-http/index.ts:28-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L103), [packages/next/src/server/base-http/node.ts:19-169](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L19-L169), [packages/next/src/server/base-http/web.ts:11-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L11-L140)
> [!WARNING]
> `NodeNextRequest.stream()` can only be called once. Attempting to consume or convert the Node request body into a Web `ReadableStream` more than once throws an invariant error because the underlying Node.js stream begins flowing immediately upon attaching data handlers.
Sources: [packages/next/src/server/base-http/node.ts:42-72](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L42-L72)
### Web Response Transformation and Lifecycle
In web-standard and edge runtimes, `WebNextResponse` manages output through a `TransformStream` and a `CloseController`. When completing execution, `toResponse()` resolves pending promises, wraps body consumption if listeners are present, and returns a standard Web `Response`.
```typescript
export class WebNextResponse extends BaseNextResponse {
private headers = new Headers()
private textBody: string | undefined = undefined
private closeController = new CloseController()
public statusCode: number | undefined
public statusMessage: string | undefined
constructor(public transformStream = new TransformStream()) {
super(transformStream.writable)
}
setHeader(name: string, value: string | string[]): this {
this.headers.delete(name)
for (const val of Array.isArray(value) ? value : [value]) {
this.headers.append(name, val)
}
return this
}
}
```
Sources: [packages/next/src/server/base-http/web.ts:38-58](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L38-L58)
> [!CAUTION]
> Calling `onClose()` on a `WebNextResponse` instance that is already closed triggers an `InvariantError`. Lifecycle callbacks must be registered before the response body finishes streaming and the close controller dispatches its close event.
Sources: [packages/next/src/server/base-http/web.ts:132-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L132-L140)
## Request Metadata and State Tracking
### Overview
Next.js attaches routing context, parsed parameters, incremental cache references, and body cloning state directly to incoming HTTP request objects using a private symbol key. This avoids polluting public request properties while allowing internal modules to share request-scoped data across boundaries.
```typescript
export const NEXT_REQUEST_META = Symbol.for('NextInternalRequestMeta')
export type NextIncomingMessage = (
| BaseNextRequest
| IncomingMessage
| NextRequest
) & {
[NEXT_REQUEST_META]?: RequestMeta
}
```
Sources: [packages/next/src/server/request-meta.ts:19-27](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts#L19-L27)
### Request Metadata Operations
State attachment and retrieval are handled by helper functions that read or mutate the record stored under `NEXT_REQUEST_META`.
```typescript
export function getRequestMeta(
req: NextIncomingMessage,
key?: undefined
): RequestMeta
export function getRequestMeta(
req: NextIncomingMessage,
key: K
): RequestMeta[K]
export function getRequestMeta(
req: NextIncomingMessage,
key?: K
): RequestMeta | RequestMeta[K] {
const meta = req[NEXT_REQUEST_META] || {}
return typeof key === 'string' ? meta[key] : meta
}
export function setRequestMeta(req: NextIncomingMessage, meta: RequestMeta) {
req[NEXT_REQUEST_META] = meta
return meta
}
export function addRequestMeta(
request: NextIncomingMessage,
key: K,
value: RequestMeta[K]
) {
const meta = getRequestMeta(request)
meta[key] = value
return setRequestMeta(request, meta)
}
export function removeRequestMeta(
request: NextIncomingMessage,
key: K
) {
const meta = getRequestMeta(request)
delete meta[key]
return setRequestMeta(request, meta)
}
```
Sources: [packages/next/src/server/request-meta.ts:348-408](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts#L348-L408)
### Header Patching and Cookie Support
To prevent headers set by middleware from being overwritten or dropped by downstream API routes or `getServerSideProps`, Next.js patches the response object's `setHeader` method.
```typescript
export function patchSetHeaderWithCookieSupport(
req: NextIncomingMessage,
res: PatchableResponse
) {
if (res[PATCHED_SET_HEADER]) {
return
}
const setHeader = res.setHeader.bind(res)
Object.defineProperty(res, PATCHED_SET_HEADER, {
value: true,
})
res.setHeader = (
name: string,
value: string | string[]
): PatchableResponse => {
if ('headersSent' in res && res.headersSent) {
return res
}
if (name.toLowerCase() === 'set-cookie') {
const middlewareValue = getRequestMeta(req, 'middlewareCookie')
if (
!middlewareValue ||
!Array.isArray(value) ||
!value.every((item, idx) => item === middlewareValue[idx])
) {
value = [
...new Set([
...(middlewareValue || []),
...(typeof value === 'string'
? [value]
: Array.isArray(value)
? value
: []),
]),
]
}
}
return setHeader(name, value)
}
}
```
Sources: [packages/next/src/server/lib/patch-set-header.ts:18-66](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-set-header.ts#L18-L66)
> [!NOTE]
> `patchSetHeaderWithCookieSupport` uses a symbol flag `PATCHED_SET_HEADER` to guarantee that the response object is patched at most once per request, avoiding recursive wrapper overhead when multiple handlers invoke `setHeader`.
Sources: [packages/next/src/server/lib/patch-set-header.ts:3-24](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-set-header.ts#L3-L24)
## Server Request Pipeline (`NextServer` / `NextNodeServer`)
### Overview
Server classes coordinate the core request handling loop, URL normalization, locale analysis, and routing execution for Next.js applications. Incoming requests flow through normalization routines that filter pathname information, inspect specialized request markers, and execute tracing spans.
Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661), [packages/next/src/server/base-server.ts:1747-1764](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1747-L1764)
### Pathname Normalization and Metadata
Pathnames are normalized using an ordered array of normalizers checked sequentially. If a normalizer matches the pathname, its normalization logic is applied directly.
```typescript
private normalize = (pathname: string) => {
const normalizers: Array = []
if (this.normalizers.data) {
normalizers.push(this.normalizers.data)
}
// We have to put the segment prefetch normalizer before the RSC normalizer
// because the RSC normalizer will match the prefetch RSC routes too.
if (this.normalizers.segmentPrefetchRSC) {
normalizers.push(this.normalizers.segmentPrefetchRSC)
}
if (this.normalizers.rsc) {
normalizers.push(this.normalizers.rsc)
}
for (const normalizer of normalizers) {
if (!normalizer.match(pathname)) continue
return normalizer.normalize(pathname, true)
}
return pathname
}
```
Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661)
> [!CAUTION]
> The segment prefetch normalizer must be evaluated before the React Server Components (RSC) normalizer in the array. Because the RSC normalizer matches prefetch RSC routes as well, placing it first would intercept and misroute segment prefetches.
Sources: [packages/next/src/server/base-server.ts:1644-1648](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1644-L1648)
### Request Pipeline Execution Walkthrough
The request handling pipeline coordinates tracing spans, streaming context construction, and execution routing:
1. `run()` / `runImpl()`: Wraps execution within tracing spans and dispatches the catch-all render request handler.
2. `pipe()` / `pipeImpl()`: Inspects the user-agent header, creates a cloned `RequestContext` with `supportsDynamicResponse` based on bot detection status, and determines whether streaming metadata should be served.
3. `normalizeAndAttachMetadata()`: Evaluates specialized request handlers like image optimization and pages data endpoints before standard routing.
Sources: [packages/next/src/server/base-server.ts:1663-1676](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1663-L1676), [packages/next/src/server/base-server.ts:1747-1763](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1747-L1763), [packages/next/src/server/base-server.ts:1765-1804](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1765-L1804)
### Pipeline Constants and Design Choices
| Design Choice | Benefit | Cost |
| --- | --- | --- |
| Sequential normalizer array evaluation | Deterministic matching order for overlapping patterns like RSC and segment prefetches | Linear search overhead across registered normalizers per request |
| Centralized tracing via `BaseServerSpan` | Detailed OpenTelemetry instrumentation across request lifecycles | Additional wrapper allocation per pipeline phase |
| Lazy instrumentation loading during `prepare()` | Avoids blocking server startup when instrumentation is absent | Deferred module resolution check until initialization completes |
Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661), [packages/next/src/server/base-server.ts:1714-1728](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1714-L1728), [packages/next/src/server/base-server.ts:1751-1754](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1751-L1754)
## NextNodeServer Dispatch and Route Execution
### Overview
NextNodeServer orchestrates concrete request routing and dispatch for Pages API routes, internal error pages, and image optimization pipelines. When an incoming request targets an API endpoint, `handleApiRequest` delegates execution directly to `runApi`. Similarly, internal rendering errors or specialized fallback routes trigger specific handler branches like `renderErrorToResponseImpl`, which evaluates edge function availability for special entries such as `UNDERSCORE_NOT_FOUND_ROUTE_ENTRY`.
Sources: [packages/next/src/server/next-server.ts:1232-1239](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L1232-L1239), [packages/next/src/server/next-server.ts:1356-1384](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L1356-L1384)
### Image Optimization Dispatch and Cache Flow
The image optimization subsystem processes requests via `ImageOptimizerCache` and `imageOptimizer`. It validates parameters, manages LRU disk caches or custom cache handlers, and executes image transformations.
```typescript
export async function imageOptimizer(
imageUpstream: ImageUpstream,
paramsResult: Pick,
nextConfig: { ... },
opts: { isDev?: boolean; silent?: boolean; previousCacheEntry?: IncrementalResponseCacheEntry | null }
) {
const { href, quality, width, mimeType } = paramsResult
const { buffer: upstreamBuffer, etag: upstreamEtag } = imageUpstream
const maxAge = Math.max(nextConfig.images.minimumCacheTTL, getMaxAge(imageUpstream.cacheControl))
// Detects content type, validates SVG policies, handles animated/bypass types, and optimizes buffer
}
```
Sources: [packages/next/src/server/image-optimizer.ts:1056-1095](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L1056-L1095)
### Image Optimization Execution Walkthrough
The image request processing pipeline moves through specific validation, fetching, and transformation stages:
1. `ImageOptimizerCache.validateParams()`: Inspects query parameters `url`, `w`, and `q`, verifying domain whitelist rules, local patterns, and numerical size constraints.
2. `fetchExternalImage()` / `fetchInternalImage()`: Fetches the upstream resource while checking IP restrictions, response body size limits, and redirect thresholds.
3. `imageOptimizer()`: Inspects magic numbers via `detectContentType()`, checks SVG permissions, bypasses animated or raw image types, and runs `optimizeImage()` using Sharp.
4. `sendResponse()`: Sets response headers such as `Cache-Control`, `Vary: Accept`, `Content-Disposition`, and `X-Nextjs-Cache` before streaming the optimized buffer.
Sources: [packages/next/src/server/image-optimizer.ts:387-549](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L387-L549), [packages/next/src/server/image-optimizer.ts:872-1054](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L872-L1054), [packages/next/src/server/image-optimizer.ts:1056-1236](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L1056-L1236), [packages/next/src/server/image-optimizer.ts:1292-1327](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L1292-L1327)
### Image Optimization Constants and Validation Flags
| Constant / Array | Values / Types | Purpose |
| --- | --- | --- |
| `ANIMATABLE_TYPES` | `['image/webp', 'image/png', 'image/gif']` | Formats checked for animation frames that bypass optimization |
| `BYPASS_TYPES` | `['image/svg+xml', 'image/x-icon', 'image/x-icns', 'image/bmp', 'image/jxl', 'image/heic']` | Formats returned directly without running the sharp transformer |
| `CACHE_VERSION` | `4` | Version identifier embedded into image cache key generation hashes |
| `BLUR_IMG_SIZE` | `8` | Default width assigned to generated blur placeholder images |
Sources: [packages/next/src/server/image-optimizer.ts:42-60](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L42-L60)
> [!WARNING]
> Requesting an external image whose hostname resolves to a private IP address will trigger a 400 error and throw an `ImageError`, unless `images.dangerouslyAllowLocalIP` is explicitly enabled in configuration.
Sources: [packages/next/src/server/image-optimizer.ts:878-900](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L878-L900)
## Page and App Render Dispatch
### Overview
The rendering dispatcher coordinates payload generation across both the Pages router (via React Fizz/SSR and `renderToHTMLImpl`) and the App Router (via React Flight streaming and server component rendering trees). The server pipeline constructs execution contexts, evaluates headers such as `NEXT_ROUTER_PREFETCH_HEADER` and `RSC_HEADER`, and delegates execution down to specific module renderers.
Sources: [packages/next/src/server/base-server.ts:1765-1804](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1765-L1804), [packages/next/src/server/app-render/app-render.tsx:395-470](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L395-L470), [packages/next/src/server/render.tsx:459-468](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L459-L468)
### Header Parsing and Request Modifiers
When a rendering request hits the server, `parseRequestHeaders()` inspects incoming HTTP headers to establish the exact rendering intent, distinguishing between standard RSC navigation, prefetch variants, and HMR refreshes.
```typescript
function parseRequestHeaders(
headers: IncomingHttpHeaders,
options: ParseRequestHeadersOptions
): ParsedRequestHeaders {
const isPrefetchRequest = headers[NEXT_ROUTER_PREFETCH_HEADER] === '1'
const isAppShellPrefetchRequest = headers[NEXT_ROUTER_PREFETCH_HEADER] === '3'
const isRuntimePrefetchRequest =
headers[NEXT_ROUTER_PREFETCH_HEADER] === '2' || isAppShellPrefetchRequest
const isHmrRefresh = headers[NEXT_HMR_REFRESH_HEADER] !== undefined
const isRSCRequest = isRSCRequestHeader(headers[RSC_HEADER])
// ...
```
Sources: [packages/next/src/server/app-render/app-render.tsx:395-414](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L395-L414)
### Render Options and Pipeline Execution
The `pipe()` and `pipeImpl()` methods manage request context construction, appending bot detection parameters and streaming metadata flags before executing the render delegate.
```typescript
private async pipeImpl(
fn: (
ctx: RequestContext
) => Promise,
partialContext: Omit<
RequestContext,
'renderOpts'
>
): Promise {
const ua = partialContext.req.headers['user-agent'] || ''
const ctx: RequestContext = {
...partialContext,
renderOpts: {
...this.renderOpts,
supportsDynamicResponse: !this.renderOpts.botType,
serveStreamingMetadata: shouldServeStreamingMetadata(
ua,
this.nextConfig.htmlLimitedBots
),
},
}
const payload = await fn(ctx)
```
Sources: [packages/next/src/server/base-server.ts:1779-1803](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1779-L1803)
### Parsed Request Header Constants
| Header Constant | Header Name / Value Condition | Purpose |
| --- | --- | --- |
| `NEXT_ROUTER_PREFETCH_HEADER` | `'1'` | Identifies standard client-side router prefetch requests |
| `NEXT_ROUTER_PREFETCH_HEADER` | `'2'` | Identifies runtime prefetch requests |
| `NEXT_ROUTER_PREFETCH_HEADER` | `'3'` | Identifies App Shell prefetch (omits link data and parameters) |
| `NEXT_HMR_REFRESH_HEADER` | `undefined` check | Detects HMR refresh events during development rendering |
| `RSC_HEADER` | Checked via `isRSCRequestHeader()` | Identifies React Server Component payload streams |
Sources: [packages/next/src/server/app-render/app-render.tsx:401-413](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L401-L413)
### Render Pipeline Design Trade-Offs
| Design Choice | Benefit | Cost |
| --- | --- | --- |
| Separate `renderToHTMLImpl` and Flight stream handlers | Isolates Pages router Fizz/SSR rendering logic from App Router streaming architectures | Duplicates context preparation wiring across different routing paradigms |
| Strict header-based prefetch classification (`1`, `2`, `3`) | Prevents unnecessary data resolution during shell and runtime prefetches | Requires careful client/server header synchronization |
| Dynamic stale time tree-walking (`getDynamicStaleTime`) | Avoids full server component rendering when extracting static segment configs | Recursively inspects module definitions prior to handling requests |
Sources: [packages/next/src/server/app-render/app-render.tsx:482-512](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L482-L512), [packages/next/src/server/render.tsx:459-468](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L459-L468)
> [!NOTE]
> App Shell prefetches (where `NEXT_ROUTER_PREFETCH_HEADER` is set to `'3'`) omit dynamic parameter resolution during server rendering. Any attempt to await `params` inside an App Shell prefetch will hang indefinitely, producing a param-independent shell of the route.
Sources: [packages/next/src/server/app-render/app-render.tsx:380-385](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L380-L385), [packages/next/src/server/app-render/app-render.tsx:403-404](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L403-L404)
## Development Server and Error Handling
### Overview
Development-mode execution in Next.js wraps standard request routing with performance instrumentation, memory tracking, on-demand compilation triggers, and enhanced error stack formatting. Development server implementations override core request handlers to ensure bundler service integration and error overlays operate transparently during local development.
Sources: [packages/next/src/server/dev/next-dev-server.ts:570-591](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L570-L591), [packages/next/src/server/dev/next-dev-server.ts:624-642](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L624-L642)
### Dev-Mode Request Interception and Telemetry
Incoming requests in the development server pass through `handleRequest()`, which initiates a performance trace span (`handle-request`), waits for server readiness via `this.ready?.promise`, and attaches debug flags such as `PagesErrorDebug`. Upon completion, RSS and heap metrics are captured via `process.memoryUsage()` and logged as child telemetry spans.
```typescript
public async handleRequest(
req: NodeNextRequest,
res: NodeNextResponse,
parsedUrl?: NextUrlWithParsedQuery
): Promise {
const span = trace('handle-request', undefined, { url: req.url })
const result = await span.traceAsyncFn(async () => {
await this.ready?.promise
addRequestMeta(req, 'PagesErrorDebug', this.renderOpts.ErrorDebug)
return await super.handleRequest(req, res, parsedUrl)
})
const memoryUsage = process.memoryUsage()
span
.traceChild('memory-usage', {
url: req.url,
'memory.rss': String(memoryUsage.rss),
'memory.heapUsed': String(memoryUsage.heapUsed),
'memory.heapTotal': String(memoryUsage.heapTotal),
})
.stop()
return result
}
```
Sources: [packages/next/src/server/dev/next-dev-server.ts:570-591](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L570-L591)
> [!WARNING]
> Unhandled errors thrown during `run()` in development servers are passed through `getProperError()`, formatted via `formatServerError()`, and dispatched to `logErrorWithOriginalStack()` before triggering `renderError()`. If headers have already been sent, the response status is forced to `500` with an emergency text fallback.
Sources: [packages/next/src/server/dev/next-dev-server.ts:624-642](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L624-L642)
### Instrumentation Hooks and On-Demand Compilation
The development server manages module compilation and telemetry initialization through lifecycle hooks. `loadInstrumentationModule()` checks for the presence of an instrumentation hook file, ensures it is compiled via `ensurePage()`, and retrieves the module via `getInstrumentationModule()`.
```typescript
protected async loadInstrumentationModule(): Promise {
let instrumentationModule: any
if (
this.actualInstrumentationHookFile &&
(await this.ensurePage({
page: this.actualInstrumentationHookFile!,
clientOnly: false,
definition: undefined,
})
.then(() => true)
.catch(() => false))
) {
try {
instrumentationModule = await getInstrumentationModule(
this.dir,
this.nextConfig.distDir
)
} catch (err: any) {
err.message = `An error occurred while loading instrumentation hook: ${err.message}`
throw err
}
}
return instrumentationModule
}
```
Sources: [packages/next/src/server/dev/next-dev-server.ts:714-737](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L714-L737)
### Development Server Methods and Fallback Signatures
| Method Name | Return Type | Purpose |
| --- | --- | --- |
| `handleRequest` | `Promise` | Traces dev requests, verifies server readiness, and appends memory usage spans |
| `run` | `Promise` | Strips basePath prefixes, dispatches execution to `super.run`, and catches unhandled render errors |
| `logErrorWithOriginalStack` | `void` | Delegates stack frame mapping to `this.bundlerService` |
| `loadInstrumentationModule` | `Promise` | Ensures and loads the user instrumentation file from the distribution directory |
| `ensureEdgeFunction` | `Promise` | Triggers on-demand compilation for Edge runtime worker targets |
Sources: [packages/next/src/server/dev/next-dev-server.ts:570-591](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L570-L591), [packages/next/src/server/dev/next-dev-server.ts:644-649](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L644-L649), [packages/next/src/server/dev/next-dev-server.ts:714-759](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L714-L759)
## Related
- [[Routing and Normalization]]
- [[Route Matching]]
- [[App Server Rendering]]
---
## Technical docs: Routing and Normalization
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/routing-and-normalization
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts)
- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next-routing/src/next-data.ts](https://github.com/blade47/next-routing/src/next-data.ts)
- [packages/next/src/server/normalizers/locale-route-normalizer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/locale-route-normalizer.ts)
- [packages/next/src/server/server-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/server-utils.ts)
- [packages/next/src/shared/lib/i18n/normalize-locale-path.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/i18n/normalize-locale-path.ts)
- [packages/next/src/server/route-modules/route-module.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/route-module.ts)
- [packages/next/src/shared/lib/router/router.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/router.ts)
- [packages/next/src/server/web/next-url.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/next-url.ts)
- [packages/next-routing/src/resolve-routes.ts](https://github.com/blade47/next-routing/src/resolve-routes.ts)
- [packages/next/src/server/lib/router-utils/resolve-routes.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/resolve-routes.ts)
- [packages/eslint-plugin-next/src/utils/url.ts](https://github.com/blade47/next.js/blob/main/packages/eslint-plugin-next/src/utils/url.ts)
- [packages/next/src/shared/lib/router/utils/format-next-pathname-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/format-next-pathname-info.ts)
- [packages/next/src/shared/lib/normalized-asset-prefix.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/normalized-asset-prefix.ts)
- [packages/next/src/shared/lib/router/utils/app-paths.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/app-paths.ts)
- [packages/next/src/server/normalizers/request/segment-prefix-rsc.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/request/segment-prefix-rsc.ts)
- [packages/next/src/shared/lib/page-path/normalize-data-path.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/page-path/normalize-data-path.ts)
- [packages/next/src/client/normalize-locale-path.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/normalize-locale-path.ts)
- [packages/next/src/server/route-modules/app-page/normalize-request-url.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-page/normalize-request-url.ts)
- [packages/next-routing/src/i18n.ts](https://github.com/blade47/next-routing/src/i18n.ts)
- [packages/next/src/server/normalizers/request/prefix.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/request/prefix.ts)
- [packages/next/src/server/normalizers/request/next-data.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/request/next-data.ts)
- [packages/next/src/server/route-modules/app-route/helpers/clean-url.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-route/helpers/clean-url.ts)
- [packages/next/src/server/lib/i18n-provider.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/i18n-provider.ts)
- [packages/next/src/server/normalizers/built/app/app-bundle-path-normalizer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/built/app/app-bundle-path-normalizer.ts)
- [packages/next/src/server/normalizers/normalizer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/normalizer.ts)
- [packages/next/src/server/request/pathname.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/pathname.ts)
- [packages/next/src/client/remove-locale.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/remove-locale.ts)
- [packages/next/src/server/normalizers/prefixing-normalizer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/prefixing-normalizer.ts)
- [packages/next/src/server/normalizers/request/pathname-normalizer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/request/pathname-normalizer.ts)
## Overview
Routing and Normalization in Next.js serves as the foundational canonicalization engine responsible for parsing, validating, and transforming incoming HTTP request URLs, client transitions, and internal build artifacts before they reach route matchers, middleware, or page renderers. Incoming requests often carry environmental artifacts such as configured basePath prefixes, internationalization locale segments, internal Next.js data request structures, React Server Component extensions, and malformed slashes.
Sources: [packages/next/src/server/lib/router-utils/resolve-routes.ts:153-165](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/resolve-routes.ts#L153-L165)
The normalization subsystem addresses these issues by executing structured extraction pipelines across both client and server boundaries, decoupling structural concerns via specialized normalizer classes and utility functions.
Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661)
```mermaid
flowchart TD
A["Raw Request URL"] --> B["Normalize Slashes"]
B --> C["Extract BasePath"]
C --> D["Extract Next Data URL"]
D --> E["Analyze Locale"]
E --> F["Pathname Normalizer Pipeline"]
F --> G["Route Matcher / Handler"]
```
Sources: [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts:63-109](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L63-L109)
## Pathname Information Extraction (`getNextPathnameInfo`)
The core analytical primitive for parsing request paths is `getNextPathnameInfo`, located in `packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts`. This utility inspects a raw pathname string against configuration parameters and extracts metadata into an interface called `NextPathnameInfo`.
Sources: [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts:53-61](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L53-L61)
The extraction routine checks trailing slashes, strips basePath prefixes, parses Next.js data URLs beginning with `/_next/data/`, and detects locales via `normalizeLocalePath` or `i18nProvider.analyze`.
Sources: [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts:62-111](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L62-L111)
```typescript
export interface NextPathnameInfo {
basePath?: string
buildId?: string
locale?: string
pathname: string
trailingSlash?: boolean
}
```
Sources: [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts:6-30](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L6-L30)
> [!NOTE]
> When parsing Next.js data URLs, `getNextPathnameInfo` retains the original data prefix for metadata extraction while providing a normalized inner pathname when `parseData: true` is set.
Sources: [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts:83-88](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L83-L88)
## Pathname Normalizers and Object-Oriented Hierarchy
Next.js implements an extensible object-oriented normalizer pattern defined by the `Normalizer` and `PathnameNormalizer` interfaces.
Sources: [packages/next/src/server/normalizers/normalizer.ts:1-3](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/normalizer.ts#L1-L3)
These classes encapsulate specific URL manipulation behaviors, such as stripping base paths, handling `.json` data suffixes, segment prefetch RSC extensions, and bundle path transformations.
Sources: [packages/next/src/server/normalizers/request/pathname-normalizer.ts:1-6](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/request/pathname-normalizer.ts#L1-L6)
```mermaid
classDiagram
class Normalizer {
<>
+normalize(pathname: string): string
}
class PathnameNormalizer {
<>
+match(pathname: string): boolean
+normalize(pathname: string, matched?: boolean): string
}
class PrefixPathnameNormalizer {
-prefix: string
+match(pathname: string): boolean
+normalize(pathname: string, matched?: boolean): string
}
class SuffixPathnameNormalizer {
-suffix: string
+match(pathname: string): boolean
+normalize(pathname: string, matched?: boolean): string
}
class NextDataPathnameNormalizer {
-prefix: PrefixPathnameNormalizer
-suffix: SuffixPathnameNormalizer
+match(pathname: string): boolean
+normalize(pathname: string, matched?: boolean): string
}
class LocaleRouteNormalizer {
-provider: I18NProvider
+normalize(pathname: string): string
}
Normalizer <|-- PathnameNormalizer
Normalizer <|-- PrefixPathnameNormalizer
Normalizer <|-- SuffixPathnameNormalizer
Normalizer <|-- LocaleRouteNormalizer
PathnameNormalizer <|-- NextDataPathnameNormalizer
```
Sources: [packages/next/src/server/normalizers/request/next-data.ts:7-31](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/request/next-data.ts#L7-L31)
The server instance maintains a prioritized array of normalizers in `BaseServer.normalize` to evaluate requests sequentially.
Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661)
Each normalizer implements a guard method `match(pathname)` prior to executing `normalize(pathname)`. For instance, `PrefixPathnameNormalizer` explicitly validates constructor parameters.
Sources: [packages/next/src/server/normalizers/request/prefix.ts:3-10](https://github.com/blade47/next.js/blob/main/packages/next/src/server/normalizers/request/prefix.ts#L3-L10)
## Internationalization (`i18n`) Locale Detection and Path Normalization
Internationalization routing requires detecting locales from the request pathname, subdomains, cookies, or `Accept-Language` headers, and normalizing the path by stripping the locale prefix.
Sources: [packages/next-routing/src/i18n.ts:196-269](https://github.com/blade47/next-routing/src/i18n.ts#L196-L269)
This is handled by `normalizeLocalePath`, `I18NProvider`, and routing resolvers.
Sources: [packages/next/src/shared/lib/i18n/normalize-locale-path.ts:22-61](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/i18n/normalize-locale-path.ts#L22-L61)
The `normalizeLocalePath` function splits the pathname by `/` to inspect the second segment, utilizing a `WeakMap` cache for performance.
Sources: [packages/next/src/shared/lib/i18n/normalize-locale-path.ts:8-34](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/i18n/normalize-locale-path.ts#L8-L34)
```typescript
const cache = new WeakMap()
export function normalizeLocalePath(
pathname: string,
locales?: readonly string[]
): PathLocale {
if (!locales) return { pathname }
let lowercasedLocales = cache.get(locales)
if (!lowercasedLocales) {
lowercasedLocales = locales.map((locale) => locale.toLowerCase())
cache.set(locales, lowercasedLocales)
}
const segments = pathname.split('/', 2)
if (!segments[1]) return { pathname }
const segment = segments[1].toLowerCase()
const index = lowercasedLocales.indexOf(segment)
if (index < 0) return { pathname }
const detectedLocale = locales[index]
pathname = pathname.slice(detectedLocale.length + 1) || '/'
return { pathname, detectedLocale }
}
```
Sources: [packages/next/src/shared/lib/i18n/normalize-locale-path.ts:10-61](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/i18n/normalize-locale-path.ts#L10-L61)
> [!WARNING]
> When `i18n` is configured, failing to account for locale prefixes when resolving filesystem items can result in route matching collisions or 404 errors, as app directory routes do not match i18n locale prefixes directly.
Sources: [packages/next/src/server/lib/router-utils/resolve-routes.ts:328-334](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/resolve-routes.ts#L328-L334)
## Next.js Data URL Normalization (`/_next/data/`)
Client-side data fetching for Static Generation and Server-Side Rendering utilizes JSON data files mapped under `/_next/data/{buildId}/{path}.json`.
Sources: [packages/next-routing/src/next-data.ts:5-34](https://github.com/blade47/next-routing/src/next-data.ts#L5-L34)
The normalization engine converts these data request URLs back into standard page pathnames for routing and execution.
Sources: [packages/next/src/shared/lib/page-path/normalize-data-path.ts:6-18](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/page-path/normalize-data-path.ts#L6-L18)
Both client-side utilities and server-side router utils perform this canonicalization via `normalizeDataPath`:
Sources: [packages/next-routing/src/next-data.ts:40-67](https://github.com/blade47/next-routing/src/next-data.ts#L40-L67)
```typescript
export function normalizeDataPath(pathname: string) {
if (!pathHasPrefix(pathname || '/', '/_next/data')) {
return pathname
}
pathname = pathname
.replace(/\/_next\/data\/[^/]{1,}/, '')
.replace(/\.json$/, '')
if (pathname === '/index') {
return '/'
}
return pathname
}
```
Sources: [packages/next/src/shared/lib/page-path/normalize-data-path.ts:6-18](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/page-path/normalize-data-path.ts#L6-L18)
Conversely, denormalization reconstructs the data URL format by injecting the build ID and `.json` extension.
Sources: [packages/next-routing/src/next-data.ts:37-67](https://github.com/blade47/next-routing/src/next-data.ts#L37-L67)
## App Directory Route Normalization (`normalizeAppPath`)
In the App Router (`app/` directory), file paths on disk include structural syntax such as route groups, parallel route slots, and leaf filenames.
Sources: [packages/eslint-plugin-next/src/utils/url.ts:37-61](https://github.com/blade47/next.js/blob/main/packages/eslint-plugin-next/src/utils/url.ts#L37-L61)
The `normalizeAppPath` function strips these markers to derive the public request pathname.
Sources: [packages/next/src/shared/lib/router/utils/app-paths.ts:23-52](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/app-paths.ts#L23-L52)
```typescript
export function normalizeAppPath(route: string) {
return ensureLeadingSlash(
route.split('/').reduce((pathname, segment, index, segments) => {
if (!segment) {
return pathname
}
if (isGroupSegment(segment)) {
return pathname
}
if (segment[0] === '@') {
return pathname
}
if (
(segment === 'page' || segment === 'route') &&
index === segments.length - 1
) {
return pathname
}
return `${pathname}/${segment}`
}, '')
)
}
```
Sources: [packages/next/src/shared/lib/router/utils/app-paths.ts:23-52](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/app-paths.ts#L23-L52)
To correctly prioritize parallel slot paths during route matching and manifest loading, Next.js employs `compareAppPaths`.
Sources: [packages/next/src/shared/lib/router/utils/app-paths.ts:64-70](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/app-paths.ts#L64-L70)
> [!IMPORTANT]
> `compareAppPaths` ensures that parallel slot paths containing `/@` sort before children page paths. Without this, route group prefixes like `(group)` would sort before `@`, leading to manifest mismatches in development mode.
Sources: [packages/next/src/shared/lib/router/utils/app-paths.ts:54-70](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/app-paths.ts#L54-L70)
## Request URL Canonicalization Pipeline
When an incoming HTTP request is received by the Next.js server, it undergoes a rigorous validation and normalization pipeline before middleware or route handlers execute.
Sources: [packages/next/src/server/lib/router-utils/resolve-routes.ts:118-142](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/resolve-routes.ts#L118-L142)
The pipeline checks for repeated slashes and backslashes, constructs absolute initialization URLs, peels locale and basePath prefixes, and tags data requests.
Sources: [packages/next/src/server/lib/router-utils/resolve-routes.ts:153-207](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/resolve-routes.ts#L153-L207)
```mermaid
sequenceDiagram
participant Client
participant Server as BaseServer / resolve-routes
participant Normalizer as PathnameNormalizer
participant Router as Route Matcher
Client->>Server: HTTP Request
Server->>Server: Check repeated slashes / backslashes
alt Malformed Slashes Detected
Server-->>Client: 308 Redirect
else Clean URL
Server->>Normalizer: Match & Normalize BasePath / Data / Locale
Normalizer-->>Server: Canonical Pathname
Server->>Router: Resolve Route Match / Middleware
end
```
Sources: [packages/next/src/server/lib/router-utils/resolve-routes.ts:153-165](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/resolve-routes.ts#L153-L165)
## Configuration Options and Reference Table
The routing and normalization subsystem relies on configuration properties defined in `next.config.js` and internal request headers.
Sources: [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts:32-51](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L32-L51)
| Configuration Property | Type | Default | Purpose / Behavior |
| :--- | :--- | :--- | :--- |
| `basePath` | `string` | `''` | Prefixes all application routes. |
| `i18n` | `object` | `null` | Enables internationalization routing. |
| `trailingSlash` | `boolean` | `false` | Enforces or strips trailing slashes. |
| `assetPrefix` | `string` | `''` | CDN or asset prefix URL for chunks. |
| `skipProxyUrlNormalize` | `boolean` | `false` | Bypasses automatic trailing slash normalization. |
Sources: [packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts:40-44](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L40-L44), [packages/next/src/server/lib/router-utils/resolve-routes.ts:193-202](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/resolve-routes.ts#L193-L202)
## Design Trade-offs
The routing and normalization architecture balances performance, flexibility, and compliance with HTTP standards through deliberate design choices.
Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661)
| Design Choice | Benefit | Cost / Trade-off |
| :--- | :--- | :--- |
| **WeakMap Locale Caching** | Prevents redundant lowercasing of locale arrays while allowing GC. | Small memory overhead per unique locale array reference. |
| **Pipelined Pathname Normalizers** | Decouples concerns into single-responsibility classes. | Multiple regex checks and string slicing operations per request. |
| **Strict App Path Normalization** | Strips layout, group, and slot segments for clean URLs. | Requires manifest lookups to map public paths back to disk. |
Sources: [packages/next/src/shared/lib/i18n/normalize-locale-path.ts:8-11](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/i18n/normalize-locale-path.ts#L8-L11), [packages/next/src/shared/lib/router/utils/app-paths.ts:23-52](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/app-paths.ts#L23-L52)
## Related
- [[Server Request Lifecycle]]
- [[Route Matching]]
---
## Technical docs: Route Matching
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/route-matching
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next/src/server/config-shared.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config-shared.ts)
- [packages/next/src/server/next-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts)
- [packages/next/src/server/route-matchers/pages-route-matcher.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/pages-route-matcher.ts)
- [packages/next-routing/src/resolve-routes.ts](https://github.com/blade47/next-routing/src/resolve-routes.ts)
- [packages/next/src/server/api-utils/node/api-resolver.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/api-utils/node/api-resolver.ts)
- [packages/next/src/server/lib/router-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-server.ts)
- [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts)
- [packages/next/src/server/route-matchers/app-page-route-matcher.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/app-page-route-matcher.ts)
- [packages/next/src/client/link.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/link.tsx)
- [packages/next/errors.json](https://github.com/blade47/next.js/blob/main/packages/next/errors.json)
- [packages/next/src/shared/lib/router/router.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/router.ts)
- [packages/next/src/server/route-matcher-managers/route-matcher-manager.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/route-matcher-manager.ts)
- [packages/next/src/server/lib/router-utils/typegen.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/typegen.ts)
- [packages/next/src/client/dev/hot-reloader/pages/hot-reloader-pages.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/dev/hot-reloader/pages/hot-reloader-pages.ts)
- [packages/next/src/server/route-matchers/app-route-route-matcher.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/app-route-route-matcher.ts)
- [packages/next/src/server/route-matchers/route-matcher.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/route-matcher.ts)
- [packages/next/src/server/request-meta.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts)
- [packages/next/src/server/route-modules/pages/pages-handler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/pages/pages-handler.ts)
- [packages/next/src/server/route-matchers/pages-api-route-matcher.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/pages-api-route-matcher.ts)
- [packages/next/src/server/route-modules/app-page/helpers/prerender-manifest-matcher.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-page/helpers/prerender-manifest-matcher.ts)
- [packages/next/src/server/lib/dev-bundler-service.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dev-bundler-service.ts)
- [packages/next/src/server/route-matcher-providers/pages-route-matcher-provider.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-providers/pages-route-matcher-provider.ts)
- [packages/next/src/server/route-modules/app-page/module.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-page/module.ts)
- [packages/next/src/client/image-component.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/image-component.tsx)
- [packages/next/src/server/route-matcher-providers/app-route-route-matcher-provider.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-providers/app-route-route-matcher-provider.ts)
- [packages/next/src/shared/lib/router/utils/interception-routes.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/interception-routes.ts)
- [packages/next/src/server/route-matcher-providers/app-page-route-matcher-provider.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-providers/app-page-route-matcher-provider.ts)
- [packages/next/src/server/route-matchers/locale-route-matcher.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/locale-route-matcher.ts)
- [packages/next/src/client/components/segment-cache/optimistic-routes.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/optimistic-routes.ts)
## Overview
### Overview
Route matching in Next.js is the foundational mechanism responsible for mapping incoming HTTP requests or client-side navigation paths to the correct App Router (`app/`) or Pages Router (`pages/`) execution handler. When a request hits the server or a client initiates a transition, Next.js must resolve file-system routes, dynamic slugs, internationalized locales, and API endpoints without ambiguity. The subsystem solves this through an extensible architecture composed of route matcher providers, individual route matchers, route pattern normalizers, and the `DefaultRouteMatcherManager`.
Sources: [packages/next/src/server/base-server.ts:802-848](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L802-L848)
The design separates manifest loading and route pattern transformation from the active lookup engine. Matchers are divided into static and dynamic collections, with dynamic routes sorted deterministically using specificity rules. Furthermore, client-side optimistic route prediction uses a trie-based structure to bypass server round-trips for known paths. This wiki page details the architecture, request pipelines, execution walkthroughs, and trade-offs of the Next.js route matching subsystem.
Sources: [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:19-292](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L19-L292)
---
## Route Matcher Providers and Manifest Ingestion
The route matching subsystem relies on route matcher providers to ingest build-time manifests (such as `pages-manifest.json` and `app-paths-manifest.json`) and transform them into concrete `RouteMatcher` instances. The base server configures a `DefaultRouteMatcherManager` by pushing provider instances through `BaseServer.getRouteMatchers()`.
Sources: [packages/next/src/server/base-server.ts:802-848](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L802-L848)
The supported provider classes and their corresponding manifests and route kinds include:
| Provider Class | Target Manifest | Route Kind | Description |
| :--- | :--- | :--- | :--- |
| `PagesRouteMatcherProvider` | `pages-manifest.json` | `RouteKind.PAGES` | Matches non-API page components under `pages/` |
| `PagesAPIRouteMatcherProvider` | `pages-manifest.json` | `RouteKind.PAGES_API` | Matches API route handlers under `pages/api/` |
| `AppPageRouteMatcherProvider` | `app-paths-manifest.json` | `RouteKind.APP_PAGE` | Matches React Server Component pages under `app/` |
| `AppRouteRouteMatcherProvider` | `app-paths-manifest.json` | `RouteKind.APP_ROUTE` | Matches App Router Route Handlers (`route.ts`) |
Sources: [packages/next/src/server/route-matcher-providers/pages-route-matcher-provider.ts:16-82](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-providers/pages-route-matcher-provider.ts#L16-L82), [packages/next/src/server/route-matcher-providers/app-page-route-matcher-provider.ts:13-60](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-providers/app-page-route-matcher-provider.ts#L13-L60), [packages/next/src/server/route-matcher-providers/app-route-route-matcher-provider.ts:12-47](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-providers/app-route-route-matcher-provider.ts#L12-L47)
---
## Core Matcher Hierarchy and Execution
At the core of individual route matching is the `RouteMatcher` class, which wraps a `RouteDefinition` and optionally compiles a dynamic regular expression matcher if the pathname contains dynamic route segments. Specialized subclasses like `LocaleRouteMatcher`, `PagesRouteMatcher`, and `AppPageRouteMatcher` extend this behavior to handle internationalization or specific route metadata.
Sources: [packages/next/src/server/route-matchers/route-matcher.ts:16-66](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/route-matcher.ts#L16-L66)
```mermaid
classDiagram
class RouteMatcher {
+D definition
+Array~RouteMatcher~ duplicated
+get identity()
+get isDynamic()
+match(pathname)
+test(pathname)
}
class LocaleRouteMatcher {
+get identity()
+match(pathname, options)
+test(pathname, options)
}
class PagesRouteMatcher {
}
class AppPageRouteMatcher {
+get identity()
}
class AppRouteRouteMatcher {
}
RouteMatcher <|-- LocaleRouteMatcher
RouteMatcher <|-- PagesRouteMatcher
RouteMatcher <|-- AppPageRouteMatcher
RouteMatcher <|-- AppRouteRouteMatcher
LocaleRouteMatcher <|-- PagesLocaleRouteMatcher
LocaleRouteMatcher <|-- PagesAPILocaleRouteMatcher
```
Sources: [packages/next/src/server/route-matchers/route-matcher.ts:16-66](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/route-matcher.ts#L16-L66), [packages/next/src/server/route-matchers/locale-route-matcher.ts:15-85](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/locale-route-matcher.ts#L15-L85)
When `RouteMatcher.test(pathname)` is invoked, it checks whether the matcher is dynamic. If `this.dynamic` is defined, it executes the compiled `RouteMatchFn` to extract route parameters; otherwise, it performs an exact string comparison:
```typescript
public test(pathname: string): RouteMatchResult | null {
if (this.dynamic) {
const params = this.dynamic(pathname)
if (!params) return null
return { params }
}
if (pathname === this.definition.pathname) {
return {}
}
return null
}
```
Sources: [packages/next/src/server/route-matchers/route-matcher.ts:52-65](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matchers/route-matcher.ts#L52-L65)
---
## RouteMatcherManager and Matching Order
The `DefaultRouteMatcherManager` orchestrates multiple providers and manages collections of static and dynamic matchers. During initialization or reload, it sorts dynamic routes using `getSortedRoutes` to ensure that specific static segments take precedence over dynamic slugs and catch-all routes.
Sources: [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:19-173](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L19-L173)
```mermaid
flowchart TD
A["Incoming Request Pathname"] --> B{"Is Dynamic Route?"}
B -->|No| C["Iterate matchers.static"]
C -->|Match Found| D["Yield Match"]
C -->|No Match| E{"options.skipDynamic?"}
B -->|Yes| F["Iterate matchers.dynamic (Sorted)"]
E -->|True| G["Return null"]
E -->|False| F
F -->|Match Found| D
F -->|No Match| G
```
Sources: [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:245-291](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L245-L291)
> [!WARNING]
> If a match is attempted before route compilation finishes (`this.lastCompilationID !== this.compilationID`), the manager throws an invariant error: `'Invariant: expected routes to have been loaded before match'`. This guards against requests racing route initialization.
Sources: [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:255-259](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L255-L259)
---
## Call-Chain Execution Walkthrough
When Next.js processes an incoming request inside `NextServer.handleRequest` (or the router server), route matching follows a precise, multi-step pipeline starting from URL normalization and locale analysis down to matcher evaluation and meta attachment.
Sources: [packages/next/src/server/next-server.ts:1102-1120](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L1102-L1120)
The call chain proceeds as follows:
1. **Request Normalization (`BaseServer` / `AppPageRouteModule.normalizeUrl`)**: The incoming URL pathname has repeated slashes normalized, trailing slashes adjusted, and RSC or prefetch headers inspected (`RSCPathnameNormalizer`, `SegmentPrefixRSCPathnameNormalizer`).
2. **Locale Analysis (`I18NProvider`)**: If internationalization is configured, the request pathname is analyzed to detect and strip domain or path locales.
3. **Matcher Manager Invocation (`DefaultRouteMatcherManager.match`)**: The normalized pathname (with a guaranteed leading slash via `ensureLeadingSlash`) is passed to `matchers.match(pathname, options)`.
Sources: [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:245-263](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L245-L263), [packages/next/src/server/route-modules/app-page/module.ts:116-153](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-page/module.ts#L116-L153)
4. **Static Validation (`validate`)**: `matchAll` first checks `this.matchers.static`. If `!isDynamicRoute(pathname)`, static matchers are tested instantly against the pathname.
5. **Dynamic Search and Sorting**: If no static match occurs, dynamic matchers in `this.matchers.dynamic` are evaluated in sorted order of specificity.
6. **Request Meta Attachment**: Once a `RouteMatch` object containing the `definition` and `params` is returned, it is attached to request metadata via `addRequestMeta(req, 'match', match)` to prevent redundant matching during subsequent rendering phases.
Sources: [packages/next/src/server/next-server.ts:1117-1120](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L1117-L1120), [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:264-287](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L264-L287)
---
## Client-Side Optimistic Route Matching (Segment Cache)
In the App Router client, the segment cache implements optimistic routing via `optimistic-routes.ts`. This module predicts route structures for URLs that have not been prefetched yet by traversing a trie of `KnownRoutePart` nodes.
Sources: [packages/next/src/client/components/segment-cache/optimistic-routes.ts:1-44](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/optimistic-routes.ts#L1-L44)
```mermaid
erDiagram
KnownRoutePart {
Map staticChildren
FulfilledRouteCacheEntry pattern
KnownRoutePart dynamicChild
string dynamicChildParamName
string dynamicChildParamType
}
RouteTree ||--o{ KnownRoutePart : "discovers"
FulfilledRouteCacheEntry ||--o{ KnownRoutePart : "serves as pattern"
```
Sources: [packages/next/src/client/components/segment-cache/optimistic-routes.ts:70-136](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/optimistic-routes.ts#L70-L136)
When `matchKnownRoute(now, pathname, search)` is called, it splits the pathname into segments and invokes `matchKnownRoutePart`:
- **Static Children Priority**: Exact static segment matches take precedence over dynamic children to prevent `/blog/featured` from incorrectly matching `/blog/[slug]`.
- **Dynamic Matching**: Evaluates regular dynamic segments (`[param]`, type `'d'`), required catch-alls (`[...param]`, type `'c'`), and optional catch-alls (`[[...param]]`, type `'oc'`), accumulating parameter values in `resolvedParams`.
- **Rewrite De-opt**: If a mismatch is detected due to a dynamic rewrite (`hasDynamicRewrite`), the pattern flags the entry and bails out to server resolution.
Sources: [packages/next/src/client/components/segment-cache/optimistic-routes.ts:607-693](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/optimistic-routes.ts#L607-L693), [packages/next/src/client/components/segment-cache/optimistic-routes.ts:743-845](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/optimistic-routes.ts#L743-L845)
---
## Design Trade-Offs
| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| **Manifest-Driven Providers** | Decouples route discovery from the request path; avoids filesystem IO during active requests. | Requires manifest synchronization during build or HMR compilation updates. |
| **Separated Static and Dynamic Matcher Arrays** | Allows $O(1)$ or fast direct checks for non-dynamic pathnames, bypassing regex evaluation. | Requires sorting dynamic routes upon registration to preserve specificity order. |
| **Client-Side Trie (Known Routes)** | Bypasses server round-trips for predicted route structures, improving transition performance. | Increases client memory usage (append-only trie) and requires de-opting on dynamic rewrites or interception routes. |
Sources: [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:13-17](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L13-L17), [packages/next/src/client/components/segment-cache/optimistic-routes.ts:33-44](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/optimistic-routes.ts#L33-L44)
---
## Worked Example: Server-Side Route Matching Integration
The following example demonstrates how `BaseServer` initializes route matchers and how `NextServer` consumes route matches to execute Pages API routes or render pages:
```typescript
import { DefaultRouteMatcherManager } from './route-matcher-managers/default-route-matcher-manager'
import { PagesRouteMatcherProvider } from './route-matcher-providers/pages-route-matcher-provider'
import { ServerManifestLoader } from './route-matcher-providers/helpers/manifest-loaders/server-manifest-loader'
import { PAGES_MANIFEST } from '../shared/lib/constants'
// 1. Create a server manifest loader
const manifestLoader = new ServerManifestLoader((name) => {
if (name === PAGES_MANIFEST) {
return { '/about': 'pages/about.js' }
}
return null
})
// 2. Instantiate matcher manager and register provider
const matchers = new DefaultRouteMatcherManager()
matchers.push(new PagesRouteMatcherProvider('/dist', manifestLoader))
// 3. Wait for readiness and match a pathname
await matchers.waitTillReady()
const match = await matchers.match('/about', {})
if (match) {
console.log(`Matched route definition:`, match.definition.page)
// Output: Matched route definition: /about
}
```
Sources: [packages/next/src/server/base-server.ts:802-848](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L802-L848), [packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts:37-53](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-matcher-managers/default-route-matcher-manager.ts#L37-L53)
## Related
- [[Routing and Normalization]]
- [[App Server Rendering]]
---
## Technical docs: Async Request Context
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/async-request-context
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/app-render/work-async-storage.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-async-storage.external.ts)
- [packages/next/src/server/use-cache/use-cache-wrapper.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts)
- [packages/next/src/server/async-storage/request-store.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts)
- [packages/next/src/server/app-render/after-task-async-storage-instance.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/after-task-async-storage-instance.ts)
- [packages/next/src/server/app-render/app-render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx)
- [packages/next/src/server/request/headers.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/headers.ts)
- [packages/next/src/server/app-render/work-unit-async-storage.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-unit-async-storage.external.ts)
- [packages/next/src/server/app-render/action-handler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts)
- [packages/next/src/server/app-render/work-async-storage-instance.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-async-storage-instance.ts)
- [packages/next/src/server/app-render/work-unit-async-storage-instance.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-unit-async-storage-instance.ts)
- [packages/next/src/experimental/testmode/context.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/experimental/testmode/context.ts)
- [packages/next/src/server/request/cookies.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/cookies.ts)
- [packages/next/src/server/after/after-context.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts)
- [packages/next/src/server/app-render/after-task-async-storage.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/after-task-async-storage.external.ts)
- [packages/next/src/server/web/adapter.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/adapter.ts)
- [packages/next/src/server/async-storage/with-store.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/with-store.ts)
- [packages/next/src/server/after/after.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after.ts)
- [packages/next/src/server/after/builtin-request-context.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/builtin-request-context.ts)
- [packages/next/src/server/app-render/action-async-storage-instance.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-async-storage-instance.ts)
- [packages/next/src/server/async-storage/work-store.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/work-store.ts)
- [packages/next/src/server/web/spec-extension/adapters/request-cookies.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts)
- [packages/next/src/server/app-render/async-local-storage.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/async-local-storage.ts)
- [packages/next/src/server/app-render/dynamic-access-async-storage-instance.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-access-async-storage-instance.ts)
- [packages/next/src/server/after/run-with-after.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/run-with-after.ts)
- [packages/next/src/server/app-render/console-async-storage-instance.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/console-async-storage-instance.ts)
- [packages/next/src/client/components/segment-cache/navigation-testing-lock.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/navigation-testing-lock.ts)
- [packages/next/src/server/app-render/action-async-storage.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-async-storage.external.ts)
- [packages/next/src/server/dev/use-cache-probe-worker.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/use-cache-probe-worker.ts)
- [packages/next/src/server/app-render/dynamic-access-async-storage.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-access-async-storage.external.ts)
- [packages/next/src/server/app-render/console-async-storage.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/console-async-storage.external.ts)
## Overview
Async Request Context serves as the underlying execution tracking and scoping mechanism in Next.js, managing asynchronous data flow across server rendering passes, server actions, route handlers, and background tasks. By leveraging Node.js `AsyncLocalStorage` alongside custom store implementations, it solves the problem of safely propagating request headers, cookies, render phases, and cache configurations down deeply nested component trees without relying on global mutable state or explicit prop drilling.
Key design decisions separate global work parameters from per-request metadata and cached execution scopes, preventing state leaks between independent cache boundaries and prerender passes. It interacts closely with dynamic APIs such as `headers()` and `cookies()` to enforce phase-based mutation rules, track dynamic data access, and schedule deferred background execution via `after()`. Sources: [packages/next/src/server/app-render/work-async-storage.external.ts:17-151](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-async-storage.external.ts#L17-L151), [packages/next/src/server/use-cache/use-cache-wrapper.ts:620-626](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L620-L626), [packages/next/src/server/async-storage/request-store.ts:99-123](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L99-L123), [packages/next/src/server/request/headers.ts:42-56](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/headers.ts#L42-L56), [packages/next/src/server/request/cookies.ts:35-50](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/cookies.ts#L35-L50), [packages/next/src/server/after/after-context.ts:39-53](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts#L39-L53), [packages/next/src/server/web/adapter.ts:339-346](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/adapter.ts#L339-L346)
## AsyncLocalStorage Infrastructure and Store Hierarchy
### Overview
Next.js builds its asynchronous context mechanism on top of an abstraction layer that wraps Node.js `AsyncLocalStorage`. When `AsyncLocalStorage` is unavailable in a runtime environment, the infrastructure falls back to a `FakeAsyncLocalStorage` implementation that throws errors on store operations like `run()`, `disable()`, `exit()`, and `enterWith()`. The base factory function `createAsyncLocalStorage()` inspects `globalThis.AsyncLocalStorage` to instantiate either the native instance or the fallback variant.
Sources: [packages/next/src/server/app-render/async-local-storage.ts:7-46](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/async-local-storage.ts#L7-L46)
```typescript
const maybeGlobalAsyncLocalStorage =
typeof globalThis !== 'undefined' && (globalThis as any).AsyncLocalStorage
export function createAsyncLocalStorage<
Store extends {},
>(): AsyncLocalStorage {
if (maybeGlobalAsyncLocalStorage) {
return new maybeGlobalAsyncLocalStorage()
}
return new FakeAsyncLocalStorage()
}
```
Sources: [packages/next/src/server/app-render/async-local-storage.ts:36-46](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/async-local-storage.ts#L36-L46)
### Store Hierarchy and Definitions
The application rendering engine divides execution contexts across distinct store types. Each store instance wraps `AsyncLocalStorage` with a specialized interface defining its contextual properties.
| Store Instance Module | Interface Type | Store Properties / Shape |
| :--- | :--- | :--- |
| `action-async-storage-instance.ts` | `ActionAsyncStorage` | `readonly isAction?: boolean`, `readonly isAppRoute?: boolean` |
| `console-async-storage-instance.ts` | `ConsoleAsyncStorage` | `readonly dim: boolean` |
| `dynamic-access-async-storage-instance.ts` | `DynamicAccessStorage` | `readonly abortController: AbortController` |
| `work-async-storage-instance.ts` | `WorkAsyncStorage` | *Defined via external storage module* |
| `work-unit-async-storage-instance.ts` | `WorkUnitAsyncStorage` | *Defined via external storage module* |
| `after-task-async-storage-instance.ts` | `AfterTaskAsyncStorage` | *Defined via external storage module* |
Sources: [packages/next/src/server/app-render/action-async-storage.external.ts:5-10](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-async-storage.external.ts#L5-L10), [packages/next/src/server/app-render/console-async-storage.external.ts:6-15](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/console-async-storage.external.ts#L6-L15), [packages/next/src/server/app-render/dynamic-access-async-storage.external.ts:6-10](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-access-async-storage.external.ts#L6-L10), [packages/next/src/server/app-render/action-async-storage-instance.ts:4-6](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-async-storage-instance.ts#L4-L6), [packages/next/src/server/app-render/console-async-storage-instance.ts:4-6](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/console-async-storage-instance.ts#L4-L6), [packages/next/src/server/app-render/dynamic-access-async-storage-instance.ts:4-6](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-access-async-storage-instance.ts#L4-L6)
> [!NOTE]
> `ConsoleStore` utilizes the `dim` property to control output coloring. When `dim` is set to true, log colors are dimmed to indicate that the log originates from a repeat or validation render that is irrelevant to the primary server action.
Sources: [packages/next/src/server/app-render/console-async-storage.external.ts:6-13](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/console-async-storage.external.ts#L6-L13)
### Snapshot Binding and Store Wrapping
To propagate execution contexts across asynchronous boundaries, helper utilities manage function binding and snapshot creation. `bindSnapshot` delegates to native `AsyncLocalStorage.bind()` or `FakeAsyncLocalStorage.bind()`, while `createSnapshot()` captures execution state or returns the identity function when native capabilities are absent. Sources: [packages/next/src/server/app-render/async-local-storage.ts:48-68](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/async-local-storage.ts#L48-L68)
```typescript
export function bindSnapshot(
fn: T
): T {
if (maybeGlobalAsyncLocalStorage) {
return maybeGlobalAsyncLocalStorage.bind(fn)
}
return FakeAsyncLocalStorage.bind(fn)
}
export function createSnapshot(): (
fn: (...args: TArgs) => R,
...args: TArgs
) => R {
if (maybeGlobalAsyncLocalStorage) {
return maybeGlobalAsyncLocalStorage.snapshot()
}
return function (fn: any, ...args: any[]) {
return fn(...args)
}
}
```
Sources: [packages/next/src/server/app-render/async-local-storage.ts:48-68](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/async-local-storage.ts#L48-L68)
Additionally, the generic `WithStore` type signature standardizes how storage implementations supply a context to callback functions:
```typescript
export type WithStore = (
storage: AsyncLocalStorage,
context: Context,
callback: (store: Store) => Result
) => Result
```
Sources: [packages/next/src/server/async-storage/with-store.ts:12-16](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/with-store.ts#L12-L16)
## RequestStore and HTTP Context Lifecycle
### Overview
The request store lifecycle centers on initializing per-request state, sanitizing incoming headers, binding request cookies, and bridging runtime adapters between Node.js request/response pairs and Edge handlers or probe workers. The `RequestStore` instance relies on decoupled inputs, allowing contexts to be instantiated without requiring a live Node.js `IncomingMessage` or `BaseNextRequest`. Sources: [packages/next/src/server/async-storage/request-store.ts:92-98](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L92-L98)
### Request Store Initialization and Headers Cleaning
When a request store is created for rendering via `createRequestStoreForRender`, it assigns a default phase of `'render'`, extracts headers from `req.headers`, and configures cookie update callbacks. The internal `getHeaders` helper processes raw headers using `HeadersAdapter.from(headers)` and strips internal plumbing headers such as `FLIGHT_HEADERS`, `NEXT_REQUEST_ID_HEADER`, and `NEXT_HTML_REQUEST_ID_HEADER` before sealing the headers instance. Sources: [packages/next/src/server/async-storage/request-store.ts:33-49](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L33-L49), [packages/next/src/server/async-storage/request-store.ts:158-174](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L158-L174)
```typescript
function getHeaders(headers: Headers | IncomingHttpHeaders): ReadonlyHeaders {
const cleaned = HeadersAdapter.from(headers)
for (const header of FLIGHT_HEADERS) {
cleaned.delete(header)
}
cleaned.delete(NEXT_REQUEST_ID_HEADER)
cleaned.delete(NEXT_HTML_REQUEST_ID_HEADER)
return HeadersAdapter.seal(cleaned)
}
```
Sources: [packages/next/src/server/async-storage/request-store.ts:33-49](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L33-L49)
### Middleware Cookie Merging
If middleware sets cookies on a request via the `x-middleware-set-cookie` header, `mergeMiddlewareCookies` parses the cookie string using `splitCookiesString`, wraps them in a `ResponseCookies` container, and merges them into the existing request cookies object so that subsequent `cookies()` calls can access newly written cookies. Sources: [packages/next/src/server/async-storage/request-store.ts:130-156](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L130-L156)
```typescript
function mergeMiddlewareCookies(
headers: Headers | IncomingHttpHeaders,
existingCookies: RequestCookies | ResponseCookies
) {
if (
'x-middleware-set-cookie' in headers &&
typeof headers['x-middleware-set-cookie'] === 'string'
) {
const setCookieValue = headers['x-middleware-set-cookie']
const responseHeaders = new Headers()
for (const cookie of splitCookiesString(setCookieValue)) {
responseHeaders.append('set-cookie', cookie)
}
const responseCookies = new ResponseCookies(responseHeaders)
for (const cookie of responseCookies.getAll()) {
existingCookies.set(cookie)
}
}
}
```
Sources: [packages/next/src/server/async-storage/request-store.ts:130-156](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L130-L156)
### Runtime Adapter Bridges and Worker Probes
In Edge runtimes and middleware adapters, execution bridges bind request stores using `createRequestStoreForAPI`. For example, `packages/next/src/server/web/adapter.ts` constructs implicit tags, wraps cookie updates, and runs the request and work async storage scopes around the middleware handler: Sources: [packages/next/src/server/web/adapter.ts:281-346](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/adapter.ts#L281-L346)
```typescript
const requestStore = createRequestStoreForAPI(
request,
request.nextUrl,
implicitTags,
onUpdateCookies,
previewProps
)
return await workAsyncStorage.run(workStore, () =>
workUnitAsyncStorage.run(
requestStore,
params.handler,
request,
event
)
)
```
Sources: [packages/next/src/server/web/adapter.ts:294-346](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/adapter.ts#L294-L346)
Similarly, the cache probe worker (`use-cache-probe-worker.ts`) initializes a throwaway request store from a serializable request snapshot without an underlying Node.js socket, enabling isolated re-executions for `'use cache'` deadlock detection: Sources: [packages/next/src/server/dev/use-cache-probe-worker.ts:155-167](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/use-cache-probe-worker.ts#L155-L167)
```typescript
const workUnitStore = createRequestStore({
phase: 'render',
headers: new Headers(msg.request.headers),
onUpdateCookies: undefined,
url: { pathname: msg.request.urlPathname, search: msg.request.urlSearch },
rootParams: msg.request.rootParams,
implicitTags: { tags: [], expirationsByCacheKind: new Map() },
resumeDataCache: null,
previewProps: undefined,
isHmrRefresh: msg.request.isHmrRefresh,
serverComponentsHmrCache: undefined,
fallbackParams: null,
})
```
Sources: [packages/next/src/server/dev/use-cache-probe-worker.ts:155-167](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/use-cache-probe-worker.ts#L155-L167)
| Request Store Input Property | Expected Type / Shape | Purpose in Request Lifecycle |
| :--- | :--- | :--- |
| `phase` | `RequestStore['phase']` | Defines the current execution phase (e.g., `'render'`) |
| `headers` | `Headers \| IncomingHttpHeaders` | Raw request headers before adapter sanitization |
| `onUpdateCookies` | `((cookies: string[]) => void) \| undefined` | Callback invoked when userspace mutates cookies |
| `url` | `{ pathname: string; search?: string }` | Identifies the pathname and search components of the request URL |
| `rootParams` | `Params` | Root route parameters for the active render |
| `implicitTags` | `ImplicitTags` | Cache tags implicitly associated with the request route |
| `resumeDataCache` | `ResumeDataCache \| null` | Cache used for streaming resume data during rendering |
| `previewProps` | `__ApiPreviewProps \| undefined` | Configuration properties for draft and preview modes |
| `isHmrRefresh` | `boolean \| undefined` | Flag indicating whether the request stems from a Hot Module Replacement refresh |
| `serverComponentsHmrCache` | `ServerComponentsHmrCache \| undefined` | Cache storage for Server Components during development HMR |
| `fallbackParams` | `OpaqueFallbackRouteParams \| null \| undefined` | Opaque fallback parameters for static paths |
Sources: [packages/next/src/server/async-storage/request-store.ts:99-123](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/request-store.ts#L99-L123)
## WorkStore and WorkUnitStore Architecture
### Overview
The Next.js rendering engine relies on a dual-store architecture managed via Node.js `AsyncLocalStorage` instances: `WorkStore` (via `workAsyncStorage`) and `WorkUnitStore` (via `workUnitAsyncStorage`). While `WorkStore` tracks top-level request and build configuration metadata across the entire render tree, `WorkUnitStore` encapsulates specific execution scopes such as incoming requests, cache boundaries (`"use cache"` or `unstable_cache`), prerenders, and static generation parameter sweeps. This separation ensures that request-specific state cannot leak into cached scopes. Sources: [packages/next/src/server/app-render/work-async-storage.external.ts:1-156](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-async-storage.external.ts#L1-L156), [packages/next/src/server/app-render/work-unit-async-storage.external.ts:369-426](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-unit-async-storage.external.ts#L369-L426)
### WorkStore Field Definitions and Static Generation Rules
`WorkStore` is initialized through `createWorkStore` and tracks global options, build identifiers, timeout configurations, and deduplication maps for fetch metrics and cache invocations. Sources: [packages/next/src/server/app-render/work-async-storage.external.ts:17-151](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-async-storage.external.ts#L17-L151), [packages/next/src/server/async-storage/work-store.ts:83-162](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/work-store.ts#L83-L162)
| WorkStore Property | Type | Purpose / Description |
| :--- | :--- | :--- |
| `isStaticGeneration` | `boolean` | Determines if the current pass is a static prerender. |
| `page` | `string` | File path relative to the page being rendered. |
| `route` | `string` | Normalized route path without trailing `/page` or `/route`. |
| `incrementalCache` | `IncrementalCache \| undefined` | Global or local incremental cache instance. |
| `useCacheTimeout` | `number` | Timeout limit in milliseconds for `"use cache"` executions. |
| `staticPageGenerationTimeout` | `number` | Timeout limit for static page generation. |
| `pendingCacheInvocations` | `Map>` | Intra-request deduplication map keyed by coarse cache key. |
| `runInCleanSnapshot` | `((fn: (...args: TArgs) => R, ...args: TArgs) => R)` | Executes functions inside a clean `AsyncLocalStorage` snapshot. |
Sources: [packages/next/src/server/app-render/work-async-storage.external.ts:17-151](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-async-storage.external.ts#L17-L151), [packages/next/src/server/async-storage/work-store.ts:83-162](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/work-store.ts#L83-L162)
The determination of static generation follows strict rules based on render options: Sources: [packages/next/src/server/async-storage/work-store.ts:109-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/work-store.ts#L109-L114)
```typescript
const isStaticGeneration =
!renderOpts.shouldWaitOnAllReady &&
!renderOpts.supportsDynamicResponse &&
!renderOpts.isDraftMode &&
!renderOpts.isPossibleServerAction
```
Sources: [packages/next/src/server/async-storage/work-store.ts:109-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/async-storage/work-store.ts#L109-L114)
### WorkUnitStore Variants and Cache Shadowing
`WorkUnitStore` is a union type representing different execution units. When entering a cache scope, `createUseCacheStore` constructs a `UseCacheStore` that shadows any outer request store, explicitly preventing the leakage of request-specific objects like unmasked cookies or headers while selectively copying required properties. Sources: [packages/next/src/server/app-render/work-unit-async-storage.external.ts:372-422](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-unit-async-storage.external.ts#L372-L422), [packages/next/src/server/use-cache/use-cache-wrapper.ts:640-720](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L640-L720)
| WorkUnitStore Type | Identifier String | Scope & Behavior |
| :--- | :--- | :--- |
| `RequestStore` | `'request'` | Represents an active HTTP request with cookies, headers, and resume cache. |
| `PublicUseCacheStore` | `'cache'` | Public `"use cache"` boundary isolating requests from cached output. |
| `PrivateUseCacheStore` | `'private-cache'` | Private cache boundary retaining scoped headers, cookies, and root parameters. |
| `UnstableCacheStore` | `'unstable-cache'` | Legacy `unstable_cache` scope where root parameters are `undefined`. |
| `PrerenderStore` | `'prerender'`, `'prerender-ppr'`, etc. | Manages static prerendering, streaming, and staged rendering controllers. |
| `GenerateStaticParamsStore` | `'generate-static-params'` | Tracks generation parameters (`rootParams`) during static path generation. |
Sources: [packages/next/src/server/app-render/work-unit-async-storage.external.ts:372-422](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-unit-async-storage.external.ts#L372-L422), [packages/next/src/server/use-cache/use-cache-wrapper.ts:640-720](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L640-L720)
> [!WARNING]
> Inside an `UnstableCacheStore`, `rootParams` is always hardcoded as `undefined`. Any nested `"use cache"` function attempting to access route parameters in this context will encounter `undefined` and throw an error. Sources: [packages/next/src/server/app-render/work-unit-async-storage.external.ts:391-399](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/work-unit-async-storage.external.ts#L391-L399)
### Cache Generation Walkthrough and Clean Snapshots
When generating a cache entry, Next.js detaches from request-specific contexts by executing through a series of wrappers that clear and restore the storage layers: Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:585-638](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L585-L638)
`generateCacheEntry()` calls `workStore.runInCleanSnapshot()`, which invokes `generateCacheEntryWithRestoredWorkStore()`. This function resets the asynchronous context and binds the work store via `workAsyncStorage.run()`, before passing execution to `generateCacheEntryWithCacheContext()`: Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:585-638](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L585-L638)
```typescript
function generateCacheEntry(
workStore: WorkStore,
cacheContext: CacheContext,
clientReferenceManifest: DeepReadonly,
encodedArguments: FormData | string,
fn: (...args: unknown[]) => Promise,
timeoutError: UseCacheTimeoutError,
deadlockError: UseCacheDeadlockError | undefined
) {
return workStore.runInCleanSnapshot(
generateCacheEntryWithRestoredWorkStore,
workStore,
cacheContext,
clientReferenceManifest,
encodedArguments,
fn,
timeoutError,
deadlockError
)
}
```
Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:585-609](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L585-L609)
> [!NOTE]
> Request stores and prerender stores are explicitly excluded from cache generation snapshots. This guarantees that request-scoped elements such as `cookies()` inside a `React.cache()` invocation cannot leak into or contaminate cached outputs. Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:620-626](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L620-L626)
## Headers and Cookies Access Adapters
### Overview
The `headers()` and `cookies()` functions provide asynchronous access to incoming HTTP request headers and request-response cookie stores. These APIs integrate with asynchronous storage to enforce dynamic tracking, validate execution phases, and prevent synchronous access or improper usage across cache scopes and background callbacks. Sources: [packages/next/src/server/request/headers.ts:33-56](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/headers.ts#L33-L56), [packages/next/src/server/request/cookies.ts:35-50](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/cookies.ts#L35-L50)
### Phase-Based Cookie Mutability Enforcement
Cookies can only be modified when the request store is operating within specific lifecycle phases, such as during a Server Action. The `areCookiesMutableInCurrentPhase` function inspects the `requestStore.phase` property to determine whether mutation is permitted. Sources: [packages/next/src/server/web/spec-extension/adapters/request-cookies.ts:208-210](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts#L208-L210)
```typescript
export function areCookiesMutableInCurrentPhase(requestStore: RequestStore) {
return requestStore.phase === 'action'
}
```
Sources: [packages/next/src/server/web/spec-extension/adapters/request-cookies.ts:208-210](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts#L208-L210)
When mutation methods like `set` or `delete` are invoked on `cookies()`, `createCookiesWithMutableAccessCheck` wraps the target store and triggers `ensureCookiesAreStillMutable()`. If the current phase has transitioned (such as moving from `action` to `render` or `render` to `after`), mutation attempts throw a `ReadonlyRequestCookiesError`. Sources: [packages/next/src/server/web/spec-extension/adapters/request-cookies.ts:181-227](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts#L181-L227)
> [!WARNING]
> Attempting to modify cookies via `cookies().set()` or `cookies().delete()` outside of a Server Action or Route Handler phase triggers `ReadonlyRequestCookiesError`, halting execution with an unmodifiable cookies error. Sources: [packages/next/src/server/web/spec-extension/adapters/request-cookies.ts:12-22](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/adapters/request-cookies.ts#L12-L22)
### Dynamic Tracking and Ergonomic Protections
Both `headers()` and `cookies()` return promises that resolve to read-only or mutable collections. To discourage synchronous access anti-patterns (such as calling properties directly on the returned promise), Next.js instruments the promise objects with warning descriptors in development mode. Sources: [packages/next/src/server/request/headers.ts:250-271](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/headers.ts#L250-L271), [packages/next/src/server/request/cookies.ts:259-278](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/cookies.ts#L259-L278)
| Instrumenting Function | Target Promise Type | Properties / Symbols Intercepted |
| :--- | :--- | :--- |
| `instrumentHeadersPromiseWithDevWarnings` | `Promise` | `Symbol.iterator`, `append`, `delete`, `get`, `has`, `set`, `getSetCookie`, `forEach`, `keys`, `values`, `entries` |
| `instrumentCookiesPromiseWithDevWarnings` | `Promise` | `Symbol.iterator`, `size`, `get`, `getAll`, `has`, `set`, `delete`, `clear`, `toString` |
Sources: [packages/next/src/server/request/headers.ts:250-271](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/headers.ts#L250-L271), [packages/next/src/server/request/cookies.ts:259-278](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/cookies.ts#L259-L278)
> [!NOTE]
> Synchronously accessing methods or properties on the unresolved `headers()` or `cookies()` promise in development invokes `createHeadersAccessError` or `createCookiesAccessError`, reminding developers to unwrap the promise using `await` or `React.use()`. Sources: [packages/next/src/server/request/headers.ts:317-327](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/headers.ts#L317-L327), [packages/next/src/server/request/cookies.ts:324-334](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/cookies.ts#L324-L334)
## After-Response Tasks and Execution Context
### Overview
The `after()` API allows developers to schedule callbacks and promises to execute after the current request finishes processing. Managing this deferred work relies on the `AfterContext` class, `AfterRunner`, and the `afterTaskAsyncStorage` instance to preserve request execution contexts and manage task error handling across background boundaries. Sources: [packages/next/src/server/after/after.ts:6-21](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after.ts#L6-L21), [packages/next/src/server/after/after-context.ts:21-37](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts#L21-L37), [packages/next/src/server/after/run-with-after.ts:12-33](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/run-with-after.ts#L12-L33)
### Scheduling and Execution Flow
When an `after()` task is submitted, execution flows through validation and queue management steps. The following call chain illustrates how a task moves from invocation to execution: Sources: [packages/next/src/server/after/after.ts:9-20](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after.ts#L9-L20), [packages/next/src/server/after/after-context.ts:39-102](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts#L39-L102)
`after()` → `workAsyncStorage.getStore()` → `afterContext.after()` → `addCallback()` → `bindSnapshot()` → `afterTaskAsyncStorage.run()` → `callbackQueue.add()`
Sources: [packages/next/src/server/after/after.ts:9-20](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after.ts#L9-L20), [packages/next/src/server/after/after-context.ts:39-102](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts#L39-L102)
> [!WARNING]
> Calling `after()` outside of a request scope throws an error (`\`after\` was called outside a request scope`), as it requires an active `workStore` containing an initialized `afterContext`. Sources: [packages/next/src/server/after/after.ts:10-17](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after.ts#L10-L17)
### `AfterContext` Options and Properties
The behavior and lifecycle of deferred tasks are governed by configuration options passed into `AfterContext`. Sources: [packages/next/src/server/after/after-context.ts:15-37](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts#L15-L37)
| Option / Property | Type | Description |
| :--- | :--- | :--- |
| `waitUntil` | `RequestLifecycleOpts['waitUntil'] \| undefined` | Platform function to extend the lifetime of the request worker for promises and callback execution. |
| `onClose` | `RequestLifecycleOpts['onClose']` | Handler triggered when the request connection closes, initiating callback execution. |
| `onTaskError` | `RequestLifecycleOpts['onAfterTaskError'] \| undefined` | Custom error handler invoked if a background task or promise rejects. |
| `callbackQueue` | `PromiseQueue` | Internal queue managing callback execution order and concurrency. |
| `workUnitStores` | `Set` | Set tracking associated work unit stores whose phases transition to `'after'` during execution. |
Sources: [packages/next/src/server/after/after-context.ts:15-37](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts#L15-L37)
### Task Error Handling and Runner Integration
The `AfterRunner` class orchestrates request lifecycle closure and error boundaries using `AwaiterOnce`, `CloseController`, and a detached promise tracker. Sources: [packages/next/src/server/after/run-with-after.ts:12-33](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/run-with-after.ts#L12-L33)
```typescript
export class AfterRunner {
private awaiter = new AwaiterOnce()
private closeController = new CloseController()
private finishedWithoutErrors = new DetachedPromise()
readonly context: Ctx = {
waitUntil: this.awaiter.waitUntil.bind(this.awaiter),
onClose: this.closeController.onClose.bind(this.closeController),
onTaskError: (error) => this.finishedWithoutErrors.reject(error),
}
public async executeAfter() {
this.closeController.dispatchClose()
await this.awaiter.awaiting()
this.finishedWithoutErrors.resolve()
return this.finishedWithoutErrors.promise
}
}
```
Sources: [packages/next/src/server/after/run-with-after.ts:12-33](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/run-with-after.ts#L12-L33)
> [!NOTE]
> When a callback or promise passed to `after()` throws or rejects, `reportTaskError` catches the error, logs it via `console.error`, and triggers `onTaskError` if defined, wrapping any handler failures in an `InvariantError`. Sources: [packages/next/src/server/after/after-context.ts:127-151](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/after-context.ts#L127-L151)
## Related
- [[Server Request Lifecycle]]
- [[Staged Dynamic Rendering]]
---
## Technical docs: Stream Handling
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/stream-handling
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/app-render/app-render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx)
- [packages/next/src/server/pipe-readable.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts)
- [packages/next/src/server/app-render/stream-ops.node.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.node.ts)
- [packages/next/src/server/render-result.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render-result.ts)
- [packages/next/src/server/stream-utils/node-web-streams-helper.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/stream-utils/node-web-streams-helper.ts)
- [packages/next/src/server/send-response.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/send-response.ts)
- [packages/next/src/server/app-render/action-handler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts)
- [packages/next/src/server/next-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts)
- [packages/next/src/client/components/segment-cache/cache.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts)
- [packages/next/src/server/app-render/use-flight-response.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/use-flight-response.tsx)
- [packages/next/src/server/app-render/stream-ops.web.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.web.ts)
- [packages/next/src/server/app-render/app-render-prerender-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render-prerender-utils.ts)
- [packages/next/src/server/body-streams.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/body-streams.ts)
- [packages/next/src/server/base-http/node.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts)
- [packages/next/src/server/app-render/instant-validation/stream-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/stream-utils.ts)
- [packages/next/src/server/send-payload.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/send-payload.ts)
- [packages/next/src/server/app-render/stream-ops.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.ts)
- [packages/next/src/server/dev/debug-channel.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/debug-channel.ts)
- [packages/next/src/server/dev/hot-reloader-turbopack.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts)
- [packages/next/src/server/dev/hot-reloader-webpack.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-webpack.ts)
## Overview
Stream handling in Next.js bridges the gap between heterogeneous rendering environments—supporting Node.js `Readable`/`PassThrough` streams, standard Web `ReadableStream` instances, and incoming HTTP body streams. During server rendering and response generation, streaming architectures allow server components (RSC) and React Fizz SSR pipelines to emit chunks incrementally to clients, reducing time-to-first-byte (TTFB) and enabling partial prerendering (PPR) or streaming HTML hydration.
Sources: [packages/next/src/server/app-render/stream-ops.ts:1-9](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.ts#L1-L9)
Because Next.js runs across different runtimes (Node.js vs. Edge) and bundlers (Webpack vs. Turbopack), stream handling employs compile-time switches, conditional adapters, and buffered transform streams. These mechanisms guarantee backpressure management, safe stream teeing and replaying during prerendering, and clean pipe propagation to Node.js `ServerResponse` objects.
Sources: [packages/next/src/server/app-render/stream-ops.node.ts:1-10](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.node.ts#L1-L10), [packages/next/src/server/pipe-readable.ts:124-147](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L124-L147)
---
## Stream Abstraction and Compile-Time Switching
Next.js unifies Node.js streams and Web streams via conditional compilation and shared interfaces. The core stream operations router (`stream-ops.ts`) dynamically resolves to either `stream-ops.node.ts` or `stream-ops.web.ts` depending on whether `process.env.__NEXT_USE_NODE_STREAMS` is active and whether the target is the Edge runtime.
Sources: [packages/next/src/server/app-render/stream-ops.ts:27-31](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.ts#L27-L31)
Both underlying modules export an identical type surface defined as `AnyStream`:
```typescript
export type AnyStream = ReadableStream | Readable
```
Sources: [packages/next/src/server/app-render/app-render-prerender-utils.ts:4](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render-prerender-utils.ts#L4-L4)
This structural identity allows stream operators (such as `continueFizzStream`, `chainStreams`, and `streamToBuffer`) to accept either stream type without runtime casting. When running under Node.js with native stream optimizations enabled, Web Streams produced by React are converted to Node.js `Readable` instances using `Readable.fromWeb()`, allowing Next.js to leverage Node's high-performance pipeline primitives and backpressure management.
Sources: [packages/next/src/server/stream-utils/node-web-streams-helper.ts:134-157](https://github.com/blade47/next.js/blob/main/packages/next/src/server/stream-utils/node-web-streams-helper.ts#L134-L157)
| Module File | Target Runtime / Condition | Primary Implementation |
| :--- | :--- | :--- |
| `stream-ops.ts` | Compile-time dispatcher | Selects Node or Web implementation based on environment flags |
| `stream-ops.node.ts` | Node.js with `__NEXT_USE_NODE_STREAMS = true` | Uses Node.js `PassThrough`, `Transform`, and `Readable.fromWeb()` |
| `stream-ops.web.ts` | Edge runtime or Web Streams mode | Uses standard `ReadableStream`, `TransformStream`, and `.tee()` |
Sources: [packages/next/src/server/app-render/stream-ops.ts:27-31](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.ts#L27-L31), [packages/next/src/server/app-render/stream-ops.node.ts:1-17](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.node.ts#L1-L17), [packages/next/src/server/app-render/stream-ops.web.ts:1-29](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.web.ts#L1-L29)
---
## Response Piping and Backpressure Mechanics
When delivering rendered output to an HTTP client via `RenderResult.pipeToNodeResponse(res)` or `pipeToNodeResponse()`, Next.js bridges `ReadableStream` or Node `Readable` instances directly to Node.js `ServerResponse` streams.
Sources: [packages/next/src/server/render-result.ts:405-417](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render-result.ts#L405-L417)
For Web `ReadableStream` inputs, `pipe-readable.ts` creates a custom WritableStream adapter (`createWriterFromResponse`) that manages header flushing, OTEL performance metrics, and backpressure:
```typescript
export async function pipeToNodeResponse(
readable: ReadableStream,
res: ServerResponse,
waitUntilForEnd?: Promise
) {
try {
const { errored, destroyed } = res
if (errored || destroyed) return
const controller = createAbortController(res)
const writer = createWriterFromResponse(res, waitUntilForEnd)
await readable.pipeTo(writer, { signal: controller.signal })
} catch (err: any) {
if (isAbortError(err)) return
throw new Error('failed to pipe response', { cause: err })
}
}
```
Sources: [packages/next/src/server/pipe-readable.ts:124-147](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L124-L147)
> [!IMPORTANT]
> Headers are deliberately not flushed until the first chunk is written (`if (!started) { started = true; res.flushHeaders(); }`). This ensures that status codes, cookies, and headers can still be modified during early stream rendering stages before bytes hit the socket.
Sources: [packages/next/src/server/pipe-readable.ts:50-80](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L50-L80)
Backpressure is governed by the return value of `res.write(chunk)`. If `res.write()` returns `false`, indicating that the underlying kernel buffer is saturated, the writer awaits the response `drain` event before continuing the pipe operation:
```typescript
const ok = res.write(chunk)
if (!ok) {
await drained.promise
drained = new DetachedPromise()
}
```
Sources: [packages/next/src/server/pipe-readable.ts:83-98](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L83-L98)
---
## Prerendering and Replayable Streams
During static generation or Partial Prerendering (PPR), Next.js must frequently split or re-use a single React Server Components (RSC) render stream across multiple consumers (e.g., generating shell markup, inlined data scripts, and static payloads). Because standard `ReadableStream.tee()` or Node streams cannot be consumed multiple times without specialized handling, Next.js implements `ReplayableNodeStream` and `ReactServerResult`.
Sources: [packages/next/src/server/app-render/app-render-prerender-utils.ts:14-99](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render-prerender-utils.ts#L14-L99)
```mermaid
flowchart TD
A["Node.js Readable Source"] --> B["ReplayableNodeStream"]
B --> C["Buffered Chunks Array"]
B --> D["Subscribers Set"]
C --> E["createReplayStream() #1"]
C --> F["createReplayStream() #2"]
D --> G["Live Chunks (on 'data')"]
E --> H["Consumer A (Fizz SSR)"]
F --> I["Consumer B (Inlined Data)"]
```
Sources: [packages/next/src/server/app-render/app-render-prerender-utils.ts:99-221](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render-prerender-utils.ts#L99-L221)
`ReplayableNodeStream` buffers incoming chunks into memory while simultaneously notifying active subscribers. When `createReplayStream()` is called, it constructs a new Node.js `Readable` that replays all previously buffered chunks via pull-based `_read()` execution before forwarding live chunks as they arrive:
```typescript
const stream = new ReadableCtor({
read() {
if (!bufferDrained) {
bufferDrained = true
for (let i = bufferIndex; i < bufferedChunks.length; i++) {
this.push(bufferedChunks[i])
}
bufferIndex = bufferedChunks.length
if (isDone) {
this.push(null)
}
}
},
})
```
Sources: [packages/next/src/server/app-render/app-render-prerender-utils.ts:179-192](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render-prerender-utils.ts#L179-L192)
> [!NOTE]
> Buffered chunks are delivered via pull-based `_read()` rather than pushed eagerly. This prevents asynchronous task scheduling from capturing an empty `AsyncLocalStorage` context when `createReplayStream()` is invoked outside request scopes.
Sources: [packages/next/src/server/app-render/app-render-prerender-utils.ts:140-149](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render-prerender-utils.ts#L140-L149)
---
## Request Body Streams and Cloneable Bodies
Incoming HTTP request bodies (`IncomingMessage`) are processed as streams during API route execution, middleware processing, and Server Action payload decoding. Because a Node.js request stream can only be read once, `getCloneableBody()` provides body duplication capabilities with strict memory limits.
Sources: [packages/next/src/server/body-streams.ts:43-58](https://github.com/blade47/next.js/blob/main/packages/next/src/server/body-streams.ts#L43-L58)
```typescript
export function getCloneableBody(
readable: T,
sizeLimit?: number
): CloneableBody {
let buffered: Readable | null = null
// ...
return {
cloneBodyStream() {
const input = buffered ?? readable
const p1 = new PassThrough()
const p2 = new PassThrough()
let bytesRead = 0
const bodySizeLimit = sizeLimit ?? DEFAULT_BODY_CLONE_SIZE_LIMIT
let limitExceeded = false
input.on('data', (chunk) => {
if (limitExceeded) return
bytesRead += chunk.length
if (bytesRead > bodySizeLimit) {
limitExceeded = true
p1.push(null)
p2.push(null)
return
}
p1.push(chunk)
p2.push(chunk)
})
// ...
buffered = p2
return p1
}
}
}
```
Sources: [packages/next/src/server/body-streams.ts:47-115](https://github.com/blade47/next.js/blob/main/packages/next/src/server/body-streams.ts#L47-L115)
When `cloneBodyStream()` is invoked, it taps into the input stream via dual `PassThrough` streams (`p1` and `p2`), accumulating a buffered copy (`p2`) while streaming data to the caller (`p1`). If the accumulated payload exceeds `DEFAULT_BODY_CLONE_SIZE_LIMIT` (10MB), a warning is logged and both streams are terminated early to prevent unbounded memory consumption.
Sources: [packages/next/src/server/body-streams.ts:6-6](https://github.com/blade47/next.js/blob/main/packages/next/src/server/body-streams.ts#L6-L6), [packages/next/src/server/body-streams.ts:79-116](https://github.com/blade47/next.js/blob/main/packages/next/src/server/body-streams.ts#L79-L116)
---
## Inlined Data Streams and Server Action Decoding
For RSC responses rendered during App Router navigation, Flight data chunks must be injected into the HTML document as self-executing script tags (`self.__next_f.push(...)`). This is handled by `createNodeInlinedDataStream` and `createInlinedDataReadableStream`.
Sources: [packages/next/src/server/app-render/stream-ops.node.ts:908-935](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.node.ts#L908-L935), [packages/next/src/server/app-render/use-flight-response.tsx:165-220](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/use-flight-response.tsx#L165-L220)
The stream reads binary or text chunks from the RSC flight stream, serializes them into JSON instructions, and wraps them in HTML script tags with proper escaping (`htmlEscapeJsonString`). Binary chunks that cannot be decoded as valid UTF-8 strings are automatically converted to Base64 data instructions:
```typescript
const base64 = Buffer.from(
chunk.buffer,
chunk.byteOffset,
chunk.byteLength
).toString('base64')
htmlInlinedData = htmlEscapeJsonString(
JSON.stringify([INLINE_FLIGHT_PAYLOAD_BINARY, base64])
)
```
Sources: [packages/next/src/server/app-render/use-flight-response.tsx:256-267](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/use-flight-response.tsx#L256-L267)
Conversely, when decoding Server Actions (`action-handler.ts`), incoming multipart form data or JSON payloads are validated against `bodySizeLimitBytes` (defaulting to 1MB) using a size-limiting transform stream before being passed to `decodeReply` or `busboy`:
```typescript
const sizeLimitTransform = new Transform({
transform(chunk, encoding, callback) {
size += Buffer.byteLength(chunk, encoding)
if (size > bodySizeLimitBytes) {
callback(new ApiError(413, `Body exceeded ${bodySizeLimit} limit.`))
return
}
callback(null, chunk)
},
})
```
Sources: [packages/next/src/server/app-render/action-handler.ts:901-931](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L901-L931)
---
## Development Debug Channels and Buffering
In development mode, Next.js streams React debug channel events and HMR payloads to the browser over WebSockets. To prevent excessive network overhead from small, frequent stream pushes, chunks are batched using `createBufferedTransformStream` (Web Streams) or `createNodeBufferedTransformStream` (Node streams) with a 128KB buffer threshold (`MAX_DEBUG_CHANNEL_BATCH_BYTES`).
Sources: [packages/next/src/server/dev/debug-channel.ts:10-12](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/debug-channel.ts#L10-L12), [packages/next/src/server/dev/debug-channel.ts:68-93](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/debug-channel.ts#L68-L93)
```typescript
export function createBufferedTransformStream(
options: BufferedTransformOptions = {}
): TransformStream {
const { maxBufferByteLength = Infinity } = options
let bufferedChunks: Array = []
let bufferByteLength: number = 0
let pending: DetachedPromise | undefined
const flush = (controller: TransformStreamDefaultController) => {
if (bufferedChunks.length === 0) return
const chunk = new Uint8Array(bufferByteLength)
let copiedBytes = 0
for (let i = 0; i < bufferedChunks.length; i++) {
chunk.set(bufferedChunks[i], copiedBytes)
copiedBytes += bufferedChunks[i].byteLength
}
bufferedChunks.length = 0
bufferByteLength = 0
controller.enqueue(chunk)
}
// ...
}
```
Sources: [packages/next/src/server/stream-utils/node-web-streams-helper.ts:227-261](https://github.com/blade47/next.js/blob/main/packages/next/src/server/stream-utils/node-web-streams-helper.ts#L227-L261)
The transformation buffers incoming chunks until `bufferByteLength >= maxBufferByteLength`, or schedules an immediate flush via microtask (`scheduleImmediate`) if the buffer is below the limit, ensuring low latency while batching small packets.
Sources: [packages/next/src/server/stream-utils/node-web-streams-helper.ts:263-292](https://github.com/blade47/next.js/blob/main/packages/next/src/server/stream-utils/node-web-streams-helper.ts#L263-L292)
When an HMR event or HTML request debug channel is established, `connectReactDebugChannel` resolves the stream type, applies this buffered transform stream, and pushes data chunks to the browser.
Sources: [packages/next/src/server/dev/debug-channel.ts:28-97](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/debug-channel.ts#L28-L97), [packages/next/src/server/dev/hot-reloader-turbopack.ts:1278-1282](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts#L1278-L1282)
---
## Call-Chain Execution Walkthrough: Response Pipe Operation
The following sequence traces how a rendered output (`RenderResult`) is piped to an HTTP client response object:
Sources: [packages/next/src/server/render-result.ts:405-417](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render-result.ts#L405-L417)
1. **`RenderResult.pipeToNodeResponse(res)`** checks if the response payload is a Node.js `Readable` stream. If so, it delegates to `pipeNodeReadableToNodeResponse()`; otherwise, it extracts `.readable` (a Web `ReadableStream`) and calls `pipeToNodeResponse()`.
Sources: [packages/next/src/server/render-result.ts:405-417](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render-result.ts#L405-L417)
2. **`pipeToNodeResponse()`** creates an `AbortController` bound to the underlying `ServerResponse` close/error events via `createAbortController(res)`, initializes `createWriterFromResponse()`, and executes `readable.pipeTo(writer, { signal })`.
Sources: [packages/next/src/server/pipe-readable.ts:124-147](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L124-L147)
3. **`createWriterFromResponse.write(chunk)`** intercepts the first emitted chunk, flushes response headers (`res.flushHeaders()`), records OTEL client component metrics, and calls `res.write(chunk)`.
Sources: [packages/next/src/server/pipe-readable.ts:20-84](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L20-L84)
4. **Backpressure Check:** If `res.write(chunk)` returns `false`, the writer awaits `drained.promise` (which resolves on the Node `drain` event) before proceeding.
Sources: [packages/next/src/server/pipe-readable.ts:83-98](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L83-L98)
5. **Completion:** Upon stream completion, `close()` awaits any pending `waitUntil` background promises before calling `res.end()` and resolving the finish promise.
Sources: [packages/next/src/server/pipe-readable.ts:109-121](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L109-L121)
```mermaid
sequenceDiagram
participant RR as RenderResult
participant PNR as pipeToNodeResponse
participant WR as createWriterFromResponse
participant SR as ServerResponse
RR->>PNR: pipeToNodeResponse(readable, res, waitUntil)
PNR->>WR: createWriterFromResponse(res, waitUntil)
PNR->>SR: readable.pipeTo(writer, { signal })
loop For each chunk
SR->>WR: write(chunk)
alt First chunk
WR->>SR: flushHeaders()
end
WR->>SR: res.write(chunk)
alt Backpressure (false)
SR-->>WR: drain event
end
end
SR-->>WR: close / finish event
WR->>SR: await waitUntil, res.end()
```
Sources: [packages/next/src/server/render-result.ts:405-417](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render-result.ts#L405-L417), [packages/next/src/server/pipe-readable.ts:20-147](https://github.com/blade47/next.js/blob/main/packages/next/src/server/pipe-readable.ts#L20-L147)
---
## Stream Operations Design Trade-Offs
| Design Choice | Benefit | Cost / Trade-off |
| :--- | :--- | :--- |
| **Compile-Time Stream Switcher** (`stream-ops.ts`) | Eliminates runtime overhead and dead-code branches in edge vs. node bundles | Requires maintaining dual module implementations (`stream-ops.node.ts` & `stream-ops.web.ts`) with identical type surfaces |
| **Pull-Based Replay Buffering** (`ReplayableNodeStream`) | Prevents eager chunk emission from capturing empty `AsyncLocalStorage` contexts | Requires buffering stream chunks in memory until consumers read them |
| **Dual PassThrough Body Cloning** (`getCloneableBody`) | Allows simultaneous consumption by Middleware and route handlers | Doubles memory allocation for request bodies up to the size limit |
| **Buffered Debug Transformation** (`createBufferedTransformStream`) | Reduces WebSocket message frequency and serialization overhead by batching up to 128KB | Introduces minor buffering latency for debug chunk delivery |
Sources: [packages/next/src/server/app-render/stream-ops.ts:27-31](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/stream-ops.ts#L27-L31), [packages/next/src/server/app-render/app-render-prerender-utils.ts:99-149](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render-prerender-utils.ts#L99-L149), [packages/next/src/server/body-streams.ts:79-116](https://github.com/blade47/next.js/blob/main/packages/next/src/server/body-streams.ts#L79-L116), [packages/next/src/server/dev/debug-channel.ts:10-12](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/debug-channel.ts#L10-L12)
## Related
- [[App Server Rendering]]
- [[Staged Dynamic Rendering]]
---
## Technical docs: App Server Rendering
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/app-router-rendering/app-server-rendering
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/app-render/app-render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx)
- [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx)
- [packages/next/src/client/app-index.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx)
- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next/src/server/render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx)
- [packages/next/src/server/app-render/instant-validation/instant-validation.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx)
- [packages/next/src/server/app-render/collect-segment-data.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/collect-segment-data.tsx)
- [packages/next/src/server/app-render/create-component-tree.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/create-component-tree.tsx)
- [packages/next/src/server/app-render/entry-base.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/entry-base.ts)
- [packages/next/src/server/client-component-renderer-logger.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/client-component-renderer-logger.ts)
- [packages/next/src/server/app-render/action-handler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts)
- [packages/next/src/shared/lib/router/utils/parse-loader-tree.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/parse-loader-tree.ts)
## Overview
App Server Rendering coordinates the server-side generation, request processing, and React Server Component (RSC) streaming lifecycle for Next.js App Router applications. It bridges base server request reception and route dispatch with nested component tree assembly, hierarchical router state traversal, and specialized execution pipelines like Server Actions and instant validation. By orchestrating payload serialization and segment data collection across static, runtime, and dynamic rendering phases, the system delivers precise incremental updates and hydrated client states.
Sources: [packages/next/src/server/app-render/app-render.tsx:2471-2485](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L2471-L2485), [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:28-56](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L28-L56), [packages/next/src/client/app-index.tsx:349-388](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L349-L388), [packages/next/src/server/app-render/action-handler.ts:538-558](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L538-L558)
## Server Request Routing and Dispatch
### Overview
Request routing and dispatch bridge incoming HTTP requests from `BaseServer` into the application render pipeline defined in `app-render.tsx`. When a request arrives, `BaseServer` matches route patterns utilizing route matcher providers such as `AppPageRouteMatcherProvider`, `AppRouteRouteMatcherProvider`, and pages manifest loaders [packages/next/src/server/base-server.ts:98-103]. Once matched, dispatch mechanisms initialize metadata, parse request headers, configure work and request stores, and invoke `renderToHTMLOrFlightImpl` to produce either rendered HTML or serialized Flight RSC payloads [packages/next/src/server/app-render/app-render.tsx:2471-2485].
Sources: [packages/next/src/server/base-server.ts:98-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L98-L103), [packages/next/src/server/app-render/app-render.tsx:2471-2485](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L2471-L2485)
### Request Dispatch Call Chain
The execution sequence from initial request reception to stream generation flows through specific core functions:
1. `BaseServer` matches incoming URL paths using provider managers and loads route component modules.
2. `renderToHTMLOrFlightImpl` receives `req`, `res`, `url`, `pagePath`, `query`, and `renderOpts`, setting initial status codes (such as `404` for `/404` paths) and unique request timestamps [packages/next/src/server/app-render/app-render.tsx:2471-2488, 2495].
3. `ComponentMod.patchFetch()` is executed, and module loaders extract `loaderTree` properties from `routeModule.userland` [packages/next/src/server/app-render/app-render.tsx:2571-2577].
4. Request header flags (`flightRouterState`, `isPrefetchRequest`, `isRSCRequest`, `isHmrRefresh`) are extracted to determine request classification [packages/next/src/server/app-render/app-render.tsx:2599-2607].
5. Unique identifiers (`requestId` and `htmlRequestId`) are generated or parsed from headers via crypto hashing or `nanoid` [packages/next/src/server/app-render/app-render.tsx:2609-2632].
6. Implicit tags are resolved using `getImplicitTags` with `resolvedPathname`, and an `AppRenderContext` (`ctx`) object is constructed [packages/next/src/server/app-render/app-render.tsx:2644-2678].
7. `workStore.isStaticGeneration` evaluates whether to trigger `prerenderToStream` or direct dynamic rendering [packages/next/src/server/app-render/app-render.tsx:2594, 2682-2694].
Sources: [packages/next/src/server/app-render/app-render.tsx:2471-2694](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L2471-L2694)
> [!NOTE]
> Request IDs are derived using different strategies based on execution context: cryptographic SHA-1 hashes of request URLs during static generation, `crypto.randomUUID()` in Edge runtimes, and `nanoid()` in Node.js runtimes.
Sources: [packages/next/src/server/app-render/app-render.tsx:2613-2624](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L2613-L2624)
### Route Matcher Providers Reference
| Provider Class | Source File | Purpose |
| :--- | :--- | :--- |
| `AppPageRouteMatcherProvider` | `packages/next/src/server/route-matcher-providers/app-page-route-matcher-provider.ts` | Discovers and matches App Router page segments (`page.js/tsx`) |
| `AppRouteRouteMatcherProvider` | `packages/next/src/server/route-matcher-providers/app-route-route-matcher-provider.ts` | Discovers and matches App Router API route handlers (`route.js/ts`) |
| `PagesAPIRouteMatcherProvider` | `packages/next/src/server/route-matcher-providers/pages-api-route-matcher-provider.ts` | Discovers and matches legacy Pages API routes |
| `PagesRouteMatcherProvider` | `packages/next/src/server/route-matcher-providers/pages-route-matcher-provider.ts` | Discovers and matches legacy Pages router pages |
Sources: [packages/next/src/server/base-server.ts:99-102](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L99-L102)
## Component Tree and LoaderTree Construction
### Overview
Next.js parses hierarchical loader trees (`LoaderTree`) to construct the nested React Server Component tree and cache node seed data. The loader tree utility `parseLoaderTree` extracts route segments, parallel routes, and module conventions from the tree array structure, identifying the active segment key and resolving convention paths for layouts, templates, and pages.
Sources: [packages/next/src/shared/lib/router/utils/parse-loader-tree.ts:4-23](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/parse-loader-tree.ts#L4-L23)
### Loader Tree Parsing and Parameter Resolution
The loader tree structure tuple contains four primary elements: `[segment, parallelRoutes, modules, staticSiblings]`. The helper function `parseLoaderTree` extracts these fields, checking if the segment matches `DEFAULT_SEGMENT_KEY` (`__DEFAULT__`) to fall back to `modules.defaultPage`. The active convention path is resolved by checking `layout?.[1] || template?.[1] || page?.[1]`.
Sources: [packages/next/src/shared/lib/router/utils/parse-loader-tree.ts:4-23](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/router/utils/parse-loader-tree.ts#L4-L23)
Root and segment parameters are computed via recursive helper implementations that traverse down parallel route children until the root layout is reached.
```typescript
export function getRootParams(
loaderTree: LoaderTree,
getDynamicParamFromSegment: GetDynamicParamFromSegment
): Params {
return getRootParamsImpl({}, loaderTree, getDynamicParamFromSegment)
}
```
Sources: [packages/next/src/server/app-render/create-component-tree.tsx:1198-1203](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/create-component-tree.tsx#L1198-L1203)
### Seed Data and Boundary Construction
Component trees are wrapped and serialized into `CacheNodeSeedData` tuples via `createSeedData`. If segments are not runtime-prefetchable, rendering is deferred by awaiting the first late render stage (`FIRST_LATE_RENDER_STAGE`). When loading boundaries are present, `LoadingBoundaryProvider` wraps the React node element.
```typescript
function createSeedData(
ctx: AppRenderContext,
rsc: React.ReactNode,
parallelRoutes: Record,
loading: LoadingModuleData | null,
isPossiblyPartialResponse: boolean,
isRuntimePrefetchable: boolean,
varyParamsAccumulator: VaryParamsAccumulator | null
): CacheNodeSeedData {
const createElement = ctx.componentMod.createElement
if (!isRuntimePrefetchable) {
const workUnitStore = workUnitAsyncStorage.getStore()
if (workUnitStore) {
let stagedRendering: StagedRenderingController | null | undefined
switch (workUnitStore.type) {
case 'request':
case 'prerender-runtime':
stagedRendering = workUnitStore.stagedRendering
if (stagedRendering) {
const deferredRsc = rsc
rsc = stagedRendering
.waitForStage(FIRST_LATE_RENDER_STAGE)
.then(() => deferredRsc)
}
break
case 'prerender':
case 'prerender-client':
case 'validation-client':
case 'prerender-ppr':
case 'prerender-legacy':
case 'cache':
case 'private-cache':
case 'unstable-cache':
case 'generate-static-params':
break
default:
workUnitStore satisfies never
}
}
}
if (loading !== null) {
const LoadingBoundaryProvider = ctx.componentMod.LoadingBoundaryProvider
rsc = createElement(LoadingBoundaryProvider, {
loading: loading,
children: rsc,
})
}
return [
rsc,
parallelRoutes,
null,
isPossiblyPartialResponse,
varyParamsAccumulator ? getVaryParamsThenable(varyParamsAccumulator) : null,
]
}
```
Sources: [packages/next/src/server/app-render/create-component-tree.tsx:1300-1367](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/create-component-tree.tsx#L1300-L1367)
> [!NOTE]
> `createSeedData` returns a tuple structure `[rsc, parallelRoutes, null, isPossiblyPartialResponse, varyParamsAccumulatorThenable]` which forms the base seed data consumed by client-side router caches during navigation and prefetching.
Sources: [packages/next/src/server/app-render/create-component-tree.tsx:1360-1366](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/create-component-tree.tsx#L1360-L1366)
## Flight Router State Tree Traversal
### Overview
The `walkTreeWithFlightRouterState` function traverses both the server-side `loaderTreeToFilter` and the client-side `flightRouterState` simultaneously. This dual-tree walk determines at what common layout or split point differential rendering must begin for client navigations or prefetches.
Sources: [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:28-56](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L28-L56)
### Traversal and Rendering Decision Flow
The traversal inspects each node of the loader tree, matching segments and evaluating router markers to decide whether to skip component rendering, emit metadata only, or trigger component tree generation at the current level.
```typescript
const renderComponentsOnThisLevel =
!flightRouterState ||
!matchSegment(actualSegment, flightRouterState[0]) ||
flightRouterState[3] === 'refetch'
```
Sources: [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:107-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L107-L114)
### Flight Router State Control Flags
When client-side navigation or prefetching requests specific subsets of the tree, `flightRouterState[3]` carries control strings that modify traversal behavior.
| Flag / Condition | Action / Behavior | Sources |
| :--- | :--- | :--- |
| `refetch` | Forces rendering components at this level regardless of segment match | [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:112-114](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L112-L114) |
| `inside-shared-layout` | Marks the traversal as operating inside the shared layout boundary | [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:133-134](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L133-L134) |
| `metadata-only` | Short-circuits traversal to return only page metadata and router state without segment data | [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:199-237](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L199-L237) |
| Route Tree Prefetch | Invokes `createRouteTreePrefetch` to serialize structural hints without full component evaluation | [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:160-172](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L160-L172) |
Sources: [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:112-237](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L112-L237)
> [!WARNING]
> If PPR is disabled and a prefetch request encounters no `loading` component in the tree, traversal short-circuits immediately and returns only the router state, avoiding expensive sub-tree renders.
Sources: [packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx:135-145](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx#L135-L145)
## Server Action Pipeline and Execution
### Overview
Server actions enable client-initiated mutations executed on the server. The `handleAction` function in `action-handler.ts` manages incoming server action invocations, request forwarding, payload decoding, revalidations, and state synchronization across workers.
Sources: [packages/next/src/server/app-render/action-handler.ts:538-594](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L538-L594)
### Action Execution Call Chain
When an action request is identified, execution flows through a precise sequence of steps from request validation to action resolution and post-execution cleanup:
`handleAction()` → `getServerActionMetadata()` → `selectWorkerForForwarding()` → `actionAsyncStorage.run()` → `decodeReply()` / `decodeReplyFromBusboy()` → `executeActionAndPrepareForRender()` → `synchronizeMutableCookies()` → `executeRevalidates()`
Sources: [packages/next/src/server/app-render/action-handler.ts:563-1354](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L563-L1354)
### Request Validation and CSRF Protection
Before executing an action, `handleAction` verifies the request origin against the host header to prevent Cross-Site Request Forgery (CSRF). If an action ID belongs to a different worker thread, the request is forwarded via `createForwardedActionResponse`.
```typescript
if (!originHost) {
warning = 'Missing `origin` header from a forwarded Server Actions request.'
} else if (!host || originHost !== host.value) {
if (isCsrfOriginAllowed(originHost, serverActions?.allowedOrigins)) {
// Ignore it
} else {
const error = new Error('Invalid Server Actions request.')
throw error
}
}
```
Sources: [packages/next/src/server/app-render/action-handler.ts:646-707](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L646-L707)
> [!CAUTION]
> If a server action is invoked during static rendering (`workStore.isStaticGeneration`), `handleAction` immediately throws an invariant error because mutations are disallowed at build time.
Sources: [packages/next/src/server/app-render/action-handler.ts:614-618](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L614-L618)
### State Synchronization and Revalidation Pipeline
Upon successful completion of an action handler, `executeActionAndPrepareForRender` transitions the request store phase from `'action'` to `'render'`, synchronizes mutable cookies, and processes pending revalidations.
| Action Phase / Function | Target State / Operation | Sources |
| :--- | :--- | :--- |
| `requestStore.phase` | Switches from `'action'` to `'render'` after action execution | [packages/next/src/server/app-render/action-handler.ts:1312-1335](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L1312-L1335) |
| `synchronizeMutableCookies` | Updates immutable cookies in the store with mutations performed during the action | [packages/next/src/server/app-render/action-handler.ts:1337-1342](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L1337-L1342) |
| `workStore.isDraftMode` | Reflects draft mode status from `requestStore.draftMode.isEnabled` | [packages/next/src/server/app-render/action-handler.ts:1344-1347](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L1344-L1347) |
| `executeRevalidates` | Awaits and applies all pending path and tag revalidations | [packages/next/src/server/app-render/action-handler.ts:1349-1352](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L1349-L1352) |
Sources: [packages/next/src/server/app-render/action-handler.ts:1300-1354](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L1300-L1354)
> [!NOTE]
> Revalidation headers like `x-action-revalidated` are populated on the response via `addRevalidationHeader` depending on whether tags, cookies, or paths were invalidated.
Sources: [packages/next/src/server/app-render/action-handler.ts:146-200](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L146-L200)
## Segment Data Collection and Validation
### Overview
Segment data extraction and instant validation parse route payloads and manage prefetch segment streams. The subsystem relies on utilities like `traverseRootSeedDataSegments` to recursively walk router states, coordinate seed data extraction, and process individual route nodes during prefetches.
Sources: [packages/next/src/server/app-render/instant-validation/instant-validation.tsx:109-127](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx#L109-L127)
### Validation Planning and Segment Traversal
The server plans validation workflows by converting segments and route trees into serializable paths. Traversal starts at the root payload, passing each segment path and seed data structure down through child routes via parallel route keys.
```typescript
function traverseCacheNodeSegments(
path: SegmentPath,
route: FlightRouterState,
seedData: CacheNodeSeedData,
processSegment: (
segmentPath: SegmentPath,
seedData: CacheNodeSeedData
) => void
): void {
processSegment(path, seedData)
const [_segment, childRoutes] = route
const [_node, parallelRoutesData, _loading, _isPartial] = seedData
for (const parallelRouteKey in childRoutes) {
const childSeedData = parallelRoutesData[parallelRouteKey]
if (!childSeedData) {
throw new InvariantError(
`Got unexpected empty seed data during instant validation`
)
}
const childRoute = childRoutes[parallelRouteKey]
const [childSegment] = childRoute
const childPath = createChildSegmentPath(
path,
parallelRouteKey,
childSegment
)
traverseCacheNodeSegments(
childPath,
childRoute,
childSeedData,
processSegment
)
}
}
```
Sources: [packages/next/src/server/app-render/instant-validation/instant-validation.tsx:129-168](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx#L129-L168)
> [!CAUTION]
> If a parallel route key in `childRoutes` lacks corresponding `parallelRoutesData` within the cache node seed data, `traverseCacheNodeSegments` throws an `InvariantError` indicating unexpected empty seed data during instant validation.
Sources: [packages/next/src/server/app-render/instant-validation/instant-validation.tsx:145-150](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx#L145-L150)
### Prefetch Data Structures and Response Formatting
Prefetch generation relies on structured definitions for root tree prefetches, segment parameters, and response payloads. The `SegmentPrefetchResponse` format packs a build ID alongside an array of nullable segment prefetches representing terminal segments and inlined ancestors.
| Type Name | Key Fields | Purpose | Sources |
| :--- | :--- | :--- | :--- |
| `RootTreePrefetch` | `buildId`, `tree`, `staleTime` | Top-level metadata structure required before fetching segment data | [packages/next/src/server/app-render/collect-segment-data.tsx:44-48](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/collect-segment-data.tsx#L44-L48) |
| `TreePrefetchParam` | `type`, `key`, `siblings` | Describes dynamic parameter constraints and static sibling segments | [packages/next/src/server/app-render/collect-segment-data.tsx:50-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/collect-segment-data.tsx#L50-L63) |
| `SegmentPrefetchResponse` | `buildId`, `data` | Top-level response holding terminal and inlined ancestor segment data | [packages/next/src/server/app-render/collect-segment-data.tsx:91-94](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/collect-segment-data.tsx#L91-L94) |
| `SegmentPrefetch` | `rsc`, `isPartial`, `staleTime`, `varyParams` | Carries rendered React nodes, partial status, and parameter dependency sets | [packages/next/src/server/app-render/collect-segment-data.tsx:96-110](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/collect-segment-data.tsx#L96-L110) |
Sources: [packages/next/src/server/app-render/collect-segment-data.tsx:44-110](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/collect-segment-data.tsx#L44-L110)
## RSC Stream Emission and Serialization
### Overview
The client-side hydration lifecycle bridges the server-emitted Flight stream with the browser DOM via specialized segment callbacks and stream registry writers. When the browser initializes app routing, `self.__next_f` captures inlined flight segments and decodes them into a React-readable stream.
```typescript
function nextServerDataCallback(seg: FlightSegment): void {
if (seg[0] === 0) {
initialServerDataBuffer = []
} else if (seg[0] === 1) {
if (!initialServerDataBuffer)
throw new Error('Unexpected server data: missing bootstrap script.')
if (initialServerDataWriter) {
initialServerDataWriter.enqueue(encoder.encode(seg[1]))
} else {
initialServerDataBuffer.push(seg[1])
}
} else if (seg[0] === 2) {
initialFormStateData = seg[1]
} else if (seg[0] === 3) {
if (!initialServerDataBuffer)
throw new Error('Unexpected server data: missing bootstrap script.')
const binaryString = atob(seg[1])
const decodedChunk = new Uint8Array(binaryString.length)
for (var i = 0; i < binaryString.length; i++) {
decodedChunk[i] = binaryString.charCodeAt(i)
}
if (initialServerDataWriter) {
initialServerDataWriter.enqueue(decodedChunk)
} else {
initialServerDataBuffer.push(decodedChunk)
}
}
}
```
Sources: [packages/next/src/client/app-index.tsx:79-110](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L79-L110)
> [!WARNING]
> If a segment with type `1` or `3` arrives before a bootstrap segment of type `0` has initialized `initialServerDataBuffer`, `nextServerDataCallback` throws an error stating that the server data is missing the bootstrap script.
Sources: [packages/next/src/client/app-index.tsx:83-85](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L83-L85), [packages/next/src/client/app-index.tsx:94-96](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L94-L96)
### Flight Segment Types and Payload Encoding
Flight segments emitted into `self.__next_f` use prefix tags to differentiate bootstrap markers, text chunks, form state payloads, and base64-encoded binary chunks.
| Segment Code | Tuple Shape | Purpose | Sources |
| :--- | :--- | :--- | :--- |
| `0` | `[isBootStrap: 0]` | Initializes the server data buffer array | [packages/next/src/client/app-index.tsx:59](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L59) |
| `1` | `[isNotBootstrap: 1, responsePartial: string]` | Enqueues or buffers text partial responses | [packages/next/src/client/app-index.tsx:60](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L60) |
| `2` | `[isFormState: 2, formState: any]` | Captures initial form state data | [packages/next/src/client/app-index.tsx:61](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L61) |
| `3` | `[isBinary: 3, responseBase64Partial: string]` | Decodes and buffers base64 binary chunks | [packages/next/src/client/app-index.tsx:62](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L62) |
Sources: [packages/next/src/client/app-index.tsx:58-63](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L58-L63)
### Hydration and Stream Coordination
Client initialization coordinates reader streams, client component loading instrumentation, and DOM content loaded states to complete React hydration.
```typescript
export async function hydrate(
instrumentationHooks: ClientInstrumentationHooks | null,
assetPrefix: string
) {
let staticIndicatorState: StaticIndicatorState | undefined
let webSocket: WebSocket | undefined
if (process.env.__NEXT_DEV_SERVER) {
const { createWebSocket } =
require('./dev/hot-reloader/app/web-socket') as typeof import('./dev/hot-reloader/app/web-socket')
staticIndicatorState = { pathname: null, appIsrManifest: null }
webSocket = createWebSocket(assetPrefix, staticIndicatorState)
}
const initialRSCPayload = await initialServerResponse
if (process.env.__NEXT_USE_OFFLINE) {
require('./components/offline') as typeof import('./components/offline')
}
if (initialRSCPayload.b) {
setNavigationBuildId(initialRSCPayload.b!)
} else {
setNavigationBuildId(getDeploymentId()!)
}
const initialTimestamp = Date.now()
const actionQueue: AppRouterActionQueue = createMutableActionQueue(
createInitialRouterState({
navigatedAt: initialTimestamp,
initialRSCPayload,
initialFlightStreamForCache,
location: window.location,
}),
instrumentationHooks
)
const reactEl = (
)
if (document.documentElement.id === '__next_error__') {
let element = reactEl
if (process.env.NODE_ENV !== 'production') {
const { RootLevelDevOverlayElement } =
require('../next-devtools/userspace/app/client-entry') as typeof import('../next-devtools/userspace/app/client-entry')
element = (
{element}
)
}
ReactDOMClient.createRoot(appElement, reactRootOptions).render(element)
} else {
React.startTransition(() => {
ReactDOMClient.hydrateRoot(appElement, reactEl, {
...reactRootOptions,
formState: initialFormStateData,
})
})
}
if (process.env.__NEXT_DEV_SERVER) {
const { linkGc } =
require('./app-link-gc') as typeof import('./app-link-gc')
linkGc()
}
}
```
Sources: [packages/next/src/client/app-index.tsx:349-434](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx#L349-L434)
## Related
- [[Staged Dynamic Rendering]]
- [[Client App Router]]
- [[Server Actions]]
---
## Technical docs: Staged Dynamic Rendering
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/app-router-rendering/staged-dynamic-rendering
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/app-render/app-render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx)
- [packages/next/src/server/app-render/dynamic-rendering.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts)
- [packages/next/src/server/use-cache/use-cache-wrapper.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts)
- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next/src/server/route-modules/app-route/module.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-route/module.ts)
- [packages/next/src/server/app-render/staged-rendering.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts)
- [packages/next/src/server/request/io.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/io.ts)
- [packages/next/src/server/app-render/postponed-state.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts)
- [packages/next/src/server/route-modules/pages/pages-handler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/pages/pages-handler.ts)
- [packages/next/src/server/node-environment-extensions/io-utils.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx)
- [packages/next/src/server/dynamic-rendering-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dynamic-rendering-utils.ts)
- [packages/next/src/server/app-render/sync-io-messages.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/sync-io-messages.ts)
- [packages/next/src/server/app-render/vary-params.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts)
- [packages/next/src/client/components/navigation.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts)
- [packages/next/src/server/request/params.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts)
## Overview
Staged Dynamic Rendering is an advanced rendering architecture in Next.js that structures server-side rendering into discrete lifecycle stages—ranging from early static shell generation through runtime phases to fully dynamic rendering—controlled by the `StagedRenderingController`. This model allows Next.js to isolate static components and render cacheable data without deopting an entire React tree, replacing coarse deopts with fine-grained stage progression. By coordinating triggers, tracking dynamic data access, and orchestrating delayed parameter resolutions, the system prevents unnecessary blocking while managing cache interactions and serializing Flight streams effectively.
Sources: [packages/next/src/server/app-render/app-render.tsx:944-952](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L944-L952), [packages/next/src/server/app-render/staged-rendering.ts:4-20](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L4-L20), [packages/next/src/server/app-render/dynamic-rendering.ts:6-10](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L6-L10)
## Staged Rendering Architecture and Controller
### Overview
The staged rendering lifecycle divides server rendering into sequential, controllable execution steps managed by the `StagedRenderingController` class in `staged-rendering.ts`. Progression through these stages controls when specific data kinds—such as session data, static link data, and runtime link data—become available to the React rendering tree. The controller maintains an internal map of triggers for every advanceable render stage, resolving pending promises as the render moves forward.
Sources: [packages/next/src/server/app-render/staged-rendering.ts:4-20](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L4-L20), [packages/next/src/server/app-render/staged-rendering.ts:84-106](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L84-L106)
### Render Stages and Progression Order
The progression is governed by `RENDER_STAGE_ADVANCE_ORDER`, which sequences static and runtime phases into distinct shell, early, and standard milestones before reaching the final dynamic stage.
| Render Stage | Enum Value | Category / Meaning |
| :--- | :--- | :--- |
| `RenderStage.Before` | `1` | Initial state prior to render execution. |
| `RenderStage.ShellEarlyStatic` | `10` | Early static shell phase. |
| `RenderStage.ShellStatic` | `11` | Late static shell phase (`FIRST_LATE_RENDER_STAGE`). |
| `RenderStage.EarlyStatic` | `12` | Early static data phase. |
| `RenderStage.Static` | `13` | Standard static rendering phase. |
| `RenderStage.ShellEarlyRuntime` | `20` | Early runtime session shell phase. |
| `RenderStage.ShellRuntime` | `21` | Late runtime session shell phase. |
| `RenderStage.EarlyRuntime` | `22` | Early runtime data phase. |
| `RenderStage.Runtime` | `23` | Standard runtime rendering phase. |
| `RenderStage.Dynamic` | `30` | Fully dynamic fallback rendering stage. |
| `RenderStage.Abandoned` | `40` | Render aborted or abandoned state. |
Sources: [packages/next/src/server/app-render/staged-rendering.ts:4-41](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L4-L41)
### Controller Trigger Coordination and Lifecycle Execution
The `StagedRenderingController` constructor initializes stage triggers and wires up event listeners for abort signals and abandon controllers. When `advanceStage(targetStage)` is called, the controller verifies that the target does not exceed `finalStage` and checks whether the target is ahead of `currentStage`.
Sources: [packages/next/src/server/app-render/staged-rendering.ts:108-148](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L108-L148), [packages/next/src/server/app-render/staged-rendering.ts:314-325](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L314-L325)
The stage advancement flow executes through the following call chain:
`StagedRenderingController.advanceStage()` → determines index range via `RENDER_STAGE_ADVANCE_ORDER.indexOf()` → iterates over intermediate stages calling `this.resolveStage()` → `fireStageTrigger()` → executes registered listeners in `trigger._listeners` and invokes `trigger._resolvePromise()`.
```typescript
// Example instantiation and stage progression sequence in node rendering
const stageController = new StagedRenderingController({
abortSignal: null,
abandonController: null,
shouldTrackSyncIO: false,
finalStage: null,
})
// Advance through static stages during node flight stream generation
stageController.advanceStage(RenderStage.ShellStatic)
stageController.advanceStage(RenderStage.Static)
stageController.advanceStage(RenderStage.Dynamic)
```
Sources: [packages/next/src/server/app-render/app-render.tsx:944-952](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L944-L952), [packages/next/src/server/app-render/app-render.tsx:1035-1073](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1035-L1073), [packages/next/src/server/app-render/staged-rendering.ts:314-362](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L314-L362), [packages/next/src/server/app-render/staged-rendering.ts:440-466](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L440-L466)
> [!NOTE]
> `cancelStageTrigger` suppresses unhandled rejection warnings automatically by attaching a no-op catch handler to `trigger.promise` when an abort signal rejects pending stage triggers.
Sources: [packages/next/src/server/app-render/staged-rendering.ts:124-137](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L124-L137), [packages/next/src/server/app-render/staged-rendering.ts:469-482](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L469-L482)
## Dynamic Data Access and Postpone Handling
### Overview
Dynamic data access and postponement handling govern how Next.js tracks runtime variables, deopts component trees, and coordinates client-side navigation hooks. When code reads dynamic properties or navigation parameters during prerendering, Next.js captures these occurrences via explicit tracking structures, triggers React postponements, or aborts static generation depending on the active render unit and configuration flags.
Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:1-21](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L1-L21), [packages/next/src/server/app-render/dynamic-rendering.ts:167-236](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L167-L236)
### Dynamic Tracking State and Access Annotation
The `DynamicTrackingState` structure manages properties recorded during Server Component rendering. It maintains `isDebugDynamicAccesses`, an array of `dynamicAccesses` storing individual `DynamicAccess` objects containing an optional stack trace and the accessed expression string, alongside sync error handling flags `syncDynamicErrorWithStack` and `syncDynamicErrorWithStackPostMicrotask`.
Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:84-112](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L84-L112)
The `createDynamicTrackingState(isDebugDynamicAccesses)` function instantiates this tracking object with an empty `dynamicAccesses` array and null error states. When a dynamic scope is entered, `annotateDynamicAccess(expression, prerenderStore)` pushes a new entry into `dynamicAccesses`, capturing `new Error().stack` if `isDebugDynamicAccesses` is enabled.
Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:124-133](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L124-L133), [packages/next/src/server/app-render/dynamic-rendering.ts:612-625](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L612-L625)
| Structure / Function | Type / Signature | Purpose |
| :--- | :--- | :--- |
| `DynamicAccess` | `object` | Holds optional stack trace and string expression for a dynamic read. |
| `DynamicTrackingState` | `object` | Container tracking `isDebugDynamicAccesses`, `dynamicAccesses`, and sync error states. |
| `createDynamicTrackingState` | `(isDebugDynamicAccesses?: boolean) => DynamicTrackingState` | Factory initializing a clean dynamic tracking state record. |
| `annotateDynamicAccess` | `(expression: string, prerenderStore: PrerenderStoreModern | ValidationStoreClient) => void` | Appends a dynamic access record to the tracking state if present. |
Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:84-133](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L84-L133), [packages/next/src/server/app-render/dynamic-rendering.ts:612-625](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L612-L625)
### Postponed State Mechanics and Parsing
Postponed state representations handle data and HTML segments that suspend during partial prerendering (PPR). The `DynamicState` enum distinguishes between RSC render data (`DATA = 1`) and HTML shell render phases (`HTML = 2`).
Sources: [packages/next/src/server/app-render/postponed-state.ts:15-25](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts#L15-L25)
| Enum / Value | Value / Properties | Meaning |
| :--- | :--- | :--- |
| `DynamicState.DATA` | `1` | Dynamic access occurred during the React Server Component render phase. |
| `DynamicState.HTML` | `2` | Dynamic access occurred during the HTML shell render phase. |
| `DynamicDataPostponedState` | `{ type: DynamicState.DATA, renderResumeDataCache }` | Postponed state for dynamic data payload. |
| `DynamicHTMLPostponedState` | `{ type: DynamicState.HTML, data: [...], renderResumeDataCache }` | Postponed state containing prelude state, React postponed object, and cache. |
Sources: [packages/next/src/server/app-render/postponed-state.ts:15-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts#L15-L63)
The `parsePostponedState(state, interpolatedParams, maxPostponedStateSizeBytes)` function parses a serialized postponed state string by extracting the initial length match, slicing the postponed string payload and resume data cache, and replacing fallback route parameters using `getDynamicParam` when interpolated params are provided.
Sources: [packages/next/src/server/app-render/postponed-state.ts:117-216](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts#L117-L216)
> [!WARNING]
> If parsing fails due to malformed string prefixes or JSON errors, `parsePostponedState` catches the exception, logs it, and falls back to a default `DynamicDataPostponedState` instance rather than crashing the request parser.
Sources: [packages/next/src/server/app-render/postponed-state.ts:203-215](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts#L203-L215)
### Client Navigation Hook Dynamic Bailouts
Client hooks such as `usePathname`, `useSearchParams`, `useParams`, `useSelectedLayoutSegments`, and `useSelectedLayoutSegment` invoke `useDynamicRouteParams` or `useDynamicSearchParams` during server-side rendering to signal runtime dependency.
Sources: [packages/next/src/client/components/navigation.ts:65-66](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts#L65-L66), [packages/next/src/client/components/navigation.ts:122-123](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts#L122-L123), [packages/next/src/client/components/navigation.ts:225-226](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts#L225-L226), [packages/next/src/client/components/navigation.ts:277-280](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts#L277-L280), [packages/next/src/client/components/navigation.ts:332-335](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts#L332-L335)
The dynamic hook invocation trace flows through the following call chain:
1. `useSelectedLayoutSegment()` calls `useSelectedLayoutSegments(parallelRouteKey)` — accesses layout context and retrieves parallel segment paths.
2. `useSelectedLayoutSegments()` invokes `useDynamicRouteParams('useSelectedLayoutSegments()')` — checks store types and manages cache components fallback parameters.
3. `useDynamicRouteParams()` evaluates work unit stores (`prerender-client`) and uses `makeClientHookHangingPromise` to suspend rendering when fallback parameters are present.
Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:627-642](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L627-L642), [packages/next/src/client/components/navigation.ts:332-337](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts#L332-L337)
```mermaid
sequenceDiagram
participant Nav as next/navigation
participant Dyn as dynamic-rendering.ts
participant Work as work-unit-async-storage
Nav->>Dyn: useSelectedLayoutSegment()
Dyn->>Nav: useSelectedLayoutSegments()
Nav->>Dyn: useDynamicRouteParams('useSelectedLayoutSegment()')
Dyn->>Work: workUnitAsyncStorage.getStore()
Work-->>Dyn: prerender-client workUnitStore
Dyn->>Dyn: makeClientHookHangingPromise()
```
Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:627-642](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L627-L642), [packages/next/src/client/components/navigation.ts:332-337](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/navigation.ts#L332-L337)
| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| Separation of `DynamicState.DATA` and `HTML` | Precise tracking of whether access occurred during RSC or HTML shell generation | Additional branch handling in postponed state parsers |
| Hanging promises for client hooks in `prerender-client` | Allows components to suspend cleanly as dynamic holes during PPR | Requires robust abort signal listeners to reject pending hanging promises on timeout |
| Fallback route param replacement strings | Enables serialization of postponed states with dynamic parameter segments | String manipulation overhead during state re-hydration |
Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:627-642](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L627-L642), [packages/next/src/server/app-render/postponed-state.ts:15-25](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts#L15-L25), [packages/next/src/server/app-render/postponed-state.ts:168-190](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts#L168-L190), [packages/next/src/server/dynamic-rendering-utils.ts:108-113](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dynamic-rendering-utils.ts#L108-L113)
## Dynamic Params and Staged Resolution
### Overview
Parameter resolution within staged rendering bridges static shells and dynamic server execution. Route parameters (`params`) and search parameters (`searchParams`) are accessed via async promises that leverage staged progression controls to delay unblocking until specific render boundaries or segment stages are reached.
Sources: [packages/next/src/server/request/params.ts:331-380](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts#L331-L380), [packages/next/src/server/app-render/vary-params.ts:21-35](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts#L21-L35)
### Parameter Promise Lifecycle and Staged Resolution
The lifecycle of parameter resolution coordinates execution across static and dynamic boundaries. When server routes evaluate parameters during prerendering, `createServerParamsForRoute` determines the appropriate execution path based on the active `WorkUnitStore` type.
Sources: [packages/next/src/server/request/params.ts:138-204](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts#L138-L204)
The call-chain execution walkthrough for parameter resolution proceeds as follows:
1. `createServerParamsForRoute` retrieves the current `workUnitStore` and dispatches static route params to `createStaticPrerenderParams`.
Sources: [packages/next/src/server/request/params.ts:138-158](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts#L138-L158)
2. `createStaticPrerenderParams` inspects whether `__NEXT_APP_SHELLS` is active and invokes `stagedRendering.delayUntilStage` with the late static link data stage (`RenderStage.Static`).
Sources: [packages/next/src/server/request/params.ts:359-380](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts#L359-L380), [packages/next/src/server/dynamic-rendering-utils.ts:198-199](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dynamic-rendering-utils.ts#L198-L199)
3. `delayUntilStage` obtains the underlying stage promise by invoking `this.getStagePromise(stage)`.
Sources: [packages/next/src/server/app-render/staged-rendering.ts:372-377](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L372-L377)
4. `getStagePromise` returns `this.triggers[stage].promise`, which remains pending until the staged rendering controller advances past that specific milestone.
Sources: [packages/next/src/server/app-render/staged-rendering.ts:364-366](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L364-L366)
```mermaid
sequenceDiagram
participant Route as params.ts
participant Static as createStaticPrerenderParams
participant Controller as StagedRenderingController
participant Trigger as StageTrigger
Route->>Static: createServerParamsForRoute()
Static->>Controller: delayUntilStage(RenderStage.Static)
Controller->>Trigger: getStagePromise(RenderStage.Static)
Trigger-->>Controller: pending promise
Controller-->>Route: delayed promise
```
Sources: [packages/next/src/server/request/params.ts:138-158](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts#L138-L158), [packages/next/src/server/request/params.ts:359-380](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts#L359-L380), [packages/next/src/server/app-render/staged-rendering.ts:364-377](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L364-L377)
> [!NOTE]
> Even when parameters are entirely static, they are intentionally excluded from the initial HTML shell by delaying their resolution until the static stage is reached.
Sources: [packages/next/src/server/request/params.ts:359-380](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts#L359-L380)
### Vary-Params Tracking and Accumulators
To support granular segment caching and flight serialization, Next.js tracks which parameter keys are accessed during rendering using `VaryParamsAccumulator` structures.
Sources: [packages/next/src/server/app-render/vary-params.ts:21-35](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts#L21-L35)
| Accumulator Field / Function | Type / Return | Purpose |
| :--- | :--- | :--- |
| `varyParams` | `VaryParams` (`Set`) | Mutable set accumulating parameter property accesses during render |
| `status` | `'pending' \| 'fulfilled'` | Tracks whether the thenable has finalized its vary parameter set |
| `value` | `VaryParams` | Finalized parameter key set exposed to React Flight |
| `createResponseVaryParamsAccumulator` | `ResponseVaryParamsAccumulator` | Initializes head, rootParams, and segment tracking sets |
| `createVaryingParams` | `Params` | Wraps route parameters in getter properties or Proxies to record reads |
Sources: [packages/next/src/server/app-render/vary-params.ts:21-105](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts#L21-L105), [packages/next/src/server/app-render/vary-params.ts:244-298](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts#L244-L298)
> [!TIP]
> When optional catch-all parameters are present (`[[...slug]]`), `createVaryingParams` employs a JavaScript `Proxy` to intercept `get`, `has`, and `ownKeys` traps, ensuring missing properties and enumerations correctly register as varying accesses.
Sources: [packages/next/src/server/app-render/vary-params.ts:249-281](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts#L249-L281)
| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| `Object.defineProperty` getters for standard parameters | High engine optimization potential for property reads | Requires exact key enumeration upfront |
| `Proxy` trap wrapping for optional catch-all parameters | Captures missing keys, `in` checks, and `Object.keys()` iterations | Higher runtime overhead compared to native property getters |
| Singleton `emptyVaryParamsAccumulator` | Zero memory allocation and immediate resolution for static client components | Limited to parameter-free segments |
Sources: [packages/next/src/server/app-render/vary-params.ts:71-91](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts#L71-L91), [packages/next/src/server/app-render/vary-params.ts:244-298](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/vary-params.ts#L244-L298)
## Sync IO Tracking and Node Environment Extensions
### Overview
Next.js intercepts synchronous platform operations (such as reads of current time, random number generators, or cryptographic functions) during pre-rendering to prevent non-deterministic values from being baked into static outputs. When a synchronous I/O action occurs within a pre-render or staged execution context, platform extensions capture the access, format specific diagnostic messages, and trigger stage interruptions.
Sources: [packages/next/src/server/node-environment-extensions/io-utils.tsx:13-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L13-L103), [packages/next/src/server/app-render/sync-io-messages.ts:33-85](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/sync-io-messages.ts#L33-L85)
### Synchronous Platform IO Interception and Call-Chain Execution
When code executes inside a Node environment extension, `io()` intercepts calls using a three-argument signature: `io(expression: string, type: SyncIOApiType)`. The execution flows through work-unit storage checks and controller evaluation.
```mermaid
sequenceDiagram
participant Caller as User Code / Platform API
participant IOExt as io-utils.tsx (`io`)
participant WorkUnit as workUnitAsyncStorage
participant Controller as StagedRenderingController
Caller->>IOExt: io(expression, type)
IOExt->>WorkUnit: getStore()
WorkUnit-->>IOExt: workUnitStore
alt workUnitStore.type is 'prerender' or 'prerender-runtime'
IOExt->>IOExt: check prerenderSignal.aborted
IOExt->>Dynamic: abortOnSynchronousPlatformIOAccess(...)
else workUnitStore.type is 'request'
IOExt->>Controller: shouldTrackSyncInterrupt()
Controller-->>IOExt: true/false
IOExt->>Controller: syncInterruptCurrentStageWithReason(syncIOError)
end
```
Sources: [packages/next/src/server/node-environment-extensions/io-utils.tsx:13-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L13-L103), [packages/next/src/server/app-render/staged-rendering.ts:154-185](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L154-L185)
The detailed call chain proceeds as follows:
1. `io(expression, type)` retrieves `workUnitAsyncStorage` and `workAsyncStorage`. Sources: [packages/next/src/server/node-environment-extensions/io-utils.tsx:13-15](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L13-L15)
2. Depending on `workUnitStore.type`, if it matches `'prerender'`, `'prerender-runtime'`, or `'prerender-client'`, it checks whether `prerenderSignal.aborted` is `false`. Sources: [packages/next/src/server/node-environment-extensions/io-utils.tsx:21-54](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L21-L54)
3. It calls `abortOnSynchronousPlatformIOAccess(...)`, which records the stack via `applyOwnerStack(createSyncIOError(...))` into `dynamicTracking.syncDynamicErrorWithStack` and invokes `prerenderStore.controller.abort(error)`. Sources: [packages/next/src/server/app-render/dynamic-rendering.ts:323-342](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/dynamic-rendering.ts#L323-L342), [packages/next/src/server/node-environment-extensions/io-utils.tsx:29-34](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L29-L34)
4. If `workUnitStore.type` is `'request'`, it inspects `stageController.shouldTrackSyncInterrupt()`. Sources: [packages/next/src/server/node-environment-extensions/io-utils.tsx:55-57](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L55-L57)
5. It creates either `createSyncIOError` or `createSyncIORuntimeError` based on whether the current stage is `Static`/`EarlyStatic` or `Runtime`, wraps it with `applyOwnerStack()`, and invokes `stageController.syncInterruptCurrentStageWithReason(syncIOError)`. Sources: [packages/next/src/server/node-environment-extensions/io-utils.tsx:58-77](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L58-L77)
Sources: [packages/next/src/server/node-environment-extensions/io-utils.tsx:13-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/node-environment-extensions/io-utils.tsx#L13-L103)
> [!CAUTION]
> During `EarlyRuntime` stages, synchronous I/O throws an error because the segment is runtime-prefetchable and an interruption would abort the prefetch prematurely, whereas `Runtime` stages permit synchronous I/O since non-prefetchable segments will never be runtime prefetched.
Sources: [packages/next/src/server/app-render/staged-rendering.ts:168-177](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/staged-rendering.ts#L168-L177)
### Sync IO API Types and Diagnostic Messages
Synchronous I/O tracking categorizes operations into specific API types, mapping each to dedicated documentation URLs and remediation guidance.
| SyncIOApiType | Documentation Record Keys | Associated Remediation Docs |
| :--- | :--- | :--- |
| `time` | `SYNC_IO_DOCS.time`, `SYNC_IO_CLIENT_DOCS.time`, `SYNC_IO_RUNTIME_DOCS.time` | `blocking-prerender-current-time` (+ telemetry bullet for `performance.now()`) |
| `random` | `SYNC_IO_DOCS.random`, `SYNC_IO_CLIENT_DOCS.random`, `SYNC_IO_RUNTIME_DOCS.random` | `blocking-prerender-random` |
| `crypto` | `SYNC_IO_DOCS.crypto`, `SYNC_IO_CLIENT_DOCS.crypto`, `SYNC_IO_RUNTIME_DOCS.crypto` | `blocking-prerender-crypto` |
Sources: [packages/next/src/server/app-render/sync-io-messages.ts:1-19](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/sync-io-messages.ts#L1-L19), [packages/next/src/server/app-render/sync-io-messages.ts:21-46](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/sync-io-messages.ts#L21-L46)
> [!NOTE]
> Server-side sync I/O errors recommend fixing the issue by adding a dynamic data access like `await connection()`, caching the value with `"use cache"`, or moving rendering to a Client Component. Client-side sync I/O errors suggest wrapping in `` or moving the read into a `useEffect` or event handler.
Sources: [packages/next/src/server/app-render/sync-io-messages.ts:33-85](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/sync-io-messages.ts#L33-L85)
## Cache Coordination and Route Stream Generation
### Overview
Cache coordination and route stream generation unify `use-cache` semantics, resume data cache serialization, and Flight stream generation. When handling cached or dynamic data dependencies within Next.js application render workflows, cache entries are evaluated for expiration, stale times, and dynamic omission before being embedded into the React Server Components (RSC) payload or staged execution pipelines. Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:2837-2849](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L2837-L2849), [packages/next/src/server/app-render/app-render.tsx:914-964](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L914-L964)
### Cache Expiration and Dynamic Omission Semantics
During static generation or prerendering, cache entries with a revalidate value of `0` or an expiration time under the dynamic expiration threshold are omitted from the static shell. This creates a dynamic hole filled during resume operations. Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:2851-2892](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L2851-L2892)
| WorkUnitStore Type | Behavior on Short Expiry / Revalidate `0` | Cache Signal & Deferred Action | Sources |
| :--- | :--- | :--- | :--- |
| `prerender` | Omitted from static shell; creates dynamic hole for resume | Ends cache signal read; resolves shared cache result as `prerender-dynamic` with a hanging promise | [packages/next/src/server/use-cache/use-cache-wrapper.ts:2856-2892](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L2856-L2892) |
| `request` | Deferred to runtime or dynamic stage in development mode | Ends cache signal read (if unended); awaits devtools IO-aware promise for current or dynamic stage | [packages/next/src/server/use-cache/use-cache-wrapper.ts:2893-2917](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L2893-L2917) |
| `prerender-runtime`, `prerender-ppr`, `cache`, `unstable-cache`, etc. | Passes through without explicit static shell omission | No direct transformation; governed by enclosing context | [packages/next/src/server/use-cache/use-cache-wrapper.ts:2918-2929](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L2918-L2929) |
Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:2856-2929](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L2856-L2929)
> [!TIP]
> When a cache entry's `revalidate` is set to `0` or its expiration falls below `DYNAMIC_EXPIRE`, the system avoids generating static pages for such data, replacing them with hanging promises that resolve via resume data caches.
Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:2851-2892](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L2851-L2892)
### Staged Dynamic Flight Render and Resume Data Serialization
When production staged dynamic flight renders execute in Node.js streams, the request store initializes stale time trackers, stage controllers, vary params accumulators, and async API promises. If runtime prefetching is enabled via loader trees, a prerender resume data cache and cache signal are spawned. Sources: [packages/next/src/server/app-render/app-render.tsx:914-964](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L914-L964)
The staged flight render follows a precise sequential task execution pipeline using `runInSequentialTasks`:
1. `stageController.advanceStage(RenderStage.ShellStatic)` advances the stage. Sources: [packages/next/src/server/app-render/app-render.tsx:1032-1036](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1032-L1036)
2. `workUnitAsyncStorage.run(requestStore, renderToNodeFlightStream, ...)` generates the source node flight stream. Sources: [packages/next/src/server/app-render/app-render.tsx:1037-1044](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1037-L1044)
3. `new ReplayableNodeStream(sourceStream)` creates replay streams for dynamic and static outputs, counting shell and static stage bytes. Sources: [packages/next/src/server/app-render/app-render.tsx:1046-1055](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1046-L1055)
4. `stageController.advanceStage(RenderStage.Static)` moves execution into the static stage. Sources: [packages/next/src/server/app-render/app-render.tsx:1059-1061](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1059-L1061)
5. `staleTimeIterable.close()` and `finishAccumulatingVaryParams(requestStore.varyParamsAccumulator)` flush tracking data. Sources: [packages/next/src/server/app-render/app-render.tsx:1062-1070](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1062-L1070)
6. `stageController.advanceStage(RenderStage.Dynamic)` completes the progression into the dynamic stage. Sources: [packages/next/src/server/app-render/app-render.tsx:1071-1074](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1071-L1074)
Sources: [packages/next/src/server/app-render/app-render.tsx:1032-1074](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L1032-L1074)
> [!WARNING]
> Postponed states and resume data caches serialize into string formats incorporating payload length identifiers. If fallback route params are present, replacements are serialized and prepended to ensure parameter interpolation during resumption.
Sources: [packages/next/src/server/app-render/postponed-state.ts:78-115](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/postponed-state.ts#L78-L115)
## Related
- [[App Server Rendering]]
- [[Prefetching and PPR]]
---
## Technical docs: Server Actions
URL: https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/app-router-rendering/server-actions
Relevant source files
The following files were used as context for generating this wiki page:
- [packages/next/src/server/app-render/action-handler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts)
- [packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts)
- [packages/next/src/server/dev/hot-reloader-turbopack.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts)
- [packages/next/src/server/app-render/encryption.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/encryption.ts)
- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next/src/client/app-call-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-call-server.ts)
- [packages/next/src/client/dev/hot-reloader/app/hot-reloader-app.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/dev/hot-reloader/app/hot-reloader-app.tsx)
- [packages/next/src/client/form-shared.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/form-shared.tsx)
- [packages/next/src/client/app-dir/form.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-dir/form.tsx)
- [packages/next/src/server/app-render/react-server.node.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/react-server.node.ts)
- [packages/next/src/server/lib/server-action-request-meta.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/server-action-request-meta.ts)
- [packages/next/src/server/app-render/use-flight-response.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/use-flight-response.tsx)
- [packages/next/src/server/request/params.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request/params.ts)
- [packages/next/src/client/app-index.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-index.tsx)
- [packages/next/src/server/mcp/tools/get-server-action-by-id.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/tools/get-server-action-by-id.ts)
- [packages/next/src/client/components/app-router-instance.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router-instance.ts)
- [packages/next/src/client/form.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/client/form.tsx)
- [packages/next/src/server/app-render/encryption-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/encryption-utils.ts)
- [packages/next/src/next-devtools/dev-overlay.browser.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/dev-overlay.browser.tsx)
- [packages/next/src/server/app-render/manifests-singleton.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/manifests-singleton.ts)
- [packages/next/src/server/after/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/after/index.ts)
- [packages/next/src/shared/lib/server-reference-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/server-reference-info.ts)
- [packages/next/src/client/components/segment-cache/cache.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts)
## Overview
Server Actions enable asynchronous functions defined on the server to be securely invoked from client components and form submissions, bridging client-side interactions and server-side mutations without requiring manual API route boilerplate. By handling execution pipelines, cryptographic bound argument verification, request routing, and router state reconciliation, Server Actions integrate seamlessly into Next.js rendering and caching systems.
Sources: [packages/next/src/server/app-render/action-handler.ts:1300-1354](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/action-handler.ts#L1300-L1354), [packages/next/src/server/app-render/encryption.ts:48-96](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/encryption.ts#L48-L96), [packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts:104-147](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts#L104-L147)
## Client Action Dispatch and Form Invocation
### Overview
Client-side server action invocation starts through the `callServer` function, which wraps action identifiers and arguments into a React transition. When invoked, `callServer` delegates execution to the app router's action queue via `dispatchAppRouterAction`.
Sources: [packages/next/src/client/app-call-server.ts:5-17](https://github.com/blade47/next.js/blob/main/packages/next/src/client/app-call-server.ts#L5-L17)
### Action Queue and Dispatch Execution
The action queue manages asynchronous transitions, action ordering, and concurrency state through `AppRouterActionQueue` and `dispatchAction`. When an action payload is dispatched, a deferred promise is created and registered with React via `startTransition`. The call-chain execution walkthrough for processing actions proceeds through the following steps: `dispatchAction()` creates a deferred promise and `ActionQueueNode`, checks if `actionQueue.pending === null`, immediately invokes `runAction()` if empty, executes the action via `actionQueue.action()`, triggers `handleResult()` upon resolution, and advances the queue via `runRemainingActions()`.
Sources: [packages/next/src/client/components/app-router-instance.ts:71-144](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router-instance.ts#L71-L144), [packages/next/src/client/components/app-router-instance.ts:146-216](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router-instance.ts#L146-L216)
> [!NOTE]
> Navigations (`ACTION_NAVIGATE` and `ACTION_RESTORE`) take immediate priority over pending actions. When a navigation action arrives while the queue is non-empty, the current pending action is marked as `discarded = true` so its state is never applied, and the navigation starts immediately while preserving subsequent queued nodes.
> Sources: [packages/next/src/client/components/app-router-instance.ts:191-208](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/app-router-instance.ts#L191-L208)
### Form Submissions and URL Handling
Client-side form submissions are intercepted by `