vercel/next.js
A pnpm + Turborepo + Lerna monorepo (`pnpm-workspace.yaml` globs `apps/*`, `packages/*`, `bench/*`, `crates/*/js`, `turbopack/crates/*/js`) layered on top of a single Cargo workspace (`Cargo.toml`) that builds Turbopack, the next-swc transforms, and the napi bindings. The JS entrypoint is `packages/next/src/bin/next.ts`, a Commander program that lazily dynamic-imports one `src/cli/next-*.ts` module per subcommand. At runtime `next dev` forks a child process running `server/lib/start-server.ts`, which boots `server/lib/router-server.ts` (routing, middleware, dev bundler) which in turn lazily loads `server/lib/render-server.ts` → `NextNodeServer` (`server/next-server.ts`) extending the abstract `BaseServer` (`server/base-server.ts`). Storage is the filesystem: `.next/` manifests plus a pluggable `IncrementalCache` / `CacheHandler` layer. Turbopack is reached through napi via `packages/next/src/build/swc/index.ts` wrapping the Rust `Project` type in `crates/next-api/src/project.rs`.
- `packages/next/src/bin/next.ts` is the single published binary (`"bin": {"next": "./dist/bin/next"}`) and registers every subcommand on a `NextRootCommand extends Command`: `build`, `experimental-analyze`, `dev` (isDefault), `export` (hidden), `info`, `start`, `telemetry`, `typegen`, `upgrade`, `experimental-test`, `experimental-request-insights`, and an `internal` group with `trace`, `query-trace`, `post-build`, `upload-trace`, `static-routes-info`, `agent-feedback-instructions`.
- Each subcommand is code-split behind a dynamic import inside `.action()` (e.g. `import('../cli/next-export.js').then((mod) => mod.nextExport())`), so CLI startup never loads the build or dev-server graph unless that command is invoked.
- `next dev` runs as two processes: the CLI process supervises, and `fork(require.resolve('../server/lib/start-server'))` spawns the actual server with `NEXT_PRIVATE_WORKER=1`, `__NEXT_DEV_SERVER='1'`, `NEXT_PRIVATE_TRACE_ID`, and a `WATCHPACK_WATCHER_LIMIT=20` workaround on darwin; options cross the boundary over IPC messages `nextWorkerReady` → `nextWorkerOptions` → `nextServerReady`.
- `startServer()` in `server/lib/start-server.ts` creates the raw `http`/`https` server (https only when `--experimental-https` supplies a self-signed cert) and installs a `requestListener` that awaits a `handlersPromise` before delegating to the router-server handler, so the socket is listening before the bundler is ready.
- `server/lib/router-server.ts#initialize()` is the real runtime boundary: it builds the filesystem checker, optionally instantiates `setupDevBundler` + `DevBundlerService` in dev, wires `renderServer.instance = require('./render-server')`, and returns `{ requestHandler, upgradeHandler }` used by both `next dev` and `next start`.
- `BaseServer` (3459 lines) is the abstract render core; its `protected abstract` surface — `findPageComponents`, `getPagesManifest`, `getPrerenderManifest`, `renderHTML`, `getIncrementalCache`, `handleUpgrade`, `getMiddleware` — is implemented by `NextNodeServer` for Node and by a separate web/edge server under `packages/next/src/server/web/`.
- Build is one giant traced function: `build()` in `packages/next/src/build/index.ts` (4815 lines) wraps everything in a `trace('next-build')` span, loads config, runs `discoverRoutes`/`createPagesMapping`, then branches to either `turbopackBuild(telemetry)` or `webpackBuild(useBuildWorker, [...])`, and finally writes `ROUTES_MANIFEST`, `PRERENDER_MANIFEST`, `APP_PATH_ROUTES_MANIFEST` and friends via a shared `writeManifest<T>()` helper.
- Turbopack is consumed through napi: `packages/next/src/build/swc/index.ts` (1905 lines) defines a `ProjectImpl implements Project` class that forwards to native calls like `binding.projectEntrypointsSubscribe`, `binding.projectWriteAllEntrypointsToDisk`, `binding.projectClientHmrEvents`, and `binding.projectGetSourceMap`, all backed by `crates/next-api/src/project.rs`'s `ProjectContainer`/`Project` turbo-tasks types.
- The Rust workspace excludes `rspack/crates/binding` and tunes profiles aggressively — `turbo-persistence` gets `opt-level = 1` even in dev, release uses `lto = "thin"` — indicating the persistence layer and cold-build time are known hot spots.
- Storage is layered: `IncrementalCache` (`server/lib/incremental-cache/index.ts`) picks a handler from `globalThis[Symbol.for('@next/cache-handlers')].FetchCache` or falls back to `FileSystemCache`, which writes under `serverDistDir/../cache/fetch-cache`, `serverDistDir/pages`, and `serverDistDir/app`.
- Build/test commands are defined in the root `package.json`: `pnpm build` (`turbo run build`), `pnpm build-all` (adds `build-native-auto`), `pnpm --filter=next dev` for the taskr watch build, `pnpm test-unit`, and a 20-entry matrix of `test-{dev,start,deploy}-{webpack,turbo,rspack}[-experimental]` scripts that all shell into `scripts/run-jest.sh`.
- Turborepo caches `build`/`dev` on `dist/**` outputs and declares a `pack-for-isolated-tests` task producing `packed.tgz`, which is how integration tests install a real tarball of `next` rather than a symlinked workspace copy.
- The `next` package vendors its own dependencies at build time: `packages/next/taskfile.js` (3140 lines) declares an `externals[...]` map and one `ncc_*` task per bundled dep (`node-html-parser`, `@vercel/routing-utils`, `busboy`, `@babel/runtime`, …), all remapped to `next/dist/compiled/*`.
- Deployment shape for downstream users is pluggable via `config.adapterPath` (defaulting to `process.env.NEXT_ADAPTER_PATH`): after the build, `handleBuildComplete()` dynamic-imports that module and hands it an `AdapterOutputs` description of every route, so hosting platforms can consume the build without reading `.next` internals.
- CI is GitHub Actions with a reusable-workflow pattern: `build_and_test.yml` fans out to `build_reusable.yml` for `build-native`, `build-native-windows`, `build-next`, `lint`, `types-and-precompiled`, `test-cargo-unit`, `test-cargo-unit-miri`, `rust-check`, and `rustdoc-check`, each passing an `afterBuild:` shell body and a `stepName`.