CodeVetter · Repo Unpack · Extension points
vercel/next.js
Next.js is built to be extended at five distinct seams: the CLI command table, the config schema + `define-env` pipeline for feature flags, the `RouteModule` class hierarchy for new route kinds, the `CacheHandler` / adapter interfaces for hosting and storage backends, and the test-harness registries (`@gate` conditions, bundler manifests). The repo also formalises extension of the *agent* workflow itself through `.agents/skills/`, with a meta-skill for authoring new ones.
- New CLI subcommands plug into the Commander table in `bin/next.ts` — add a `.command(name)` + `.action(() => import('../cli/next-<name>.js'))` pair and a matching `Next<Name>Options` type; the `internal` sub-group shows the pattern for hidden/maintenance commands.
- A new feature flag is a four-file change by convention: the type in `server/config-shared.ts` (`ExperimentalConfig`), the zod entry in `server/config-schema.ts`, a default in `defaultConfig`, and a `process.env.__NEXT_*` entry in `build/define-env.ts` when the flag must reach user-bundled code — with the `$flags` skill documenting the runtime-env plumbing needed for pre-compiled internals.
- `RouteModule<D, U, X>` is the abstract base every route kind extends; adding a new kind means a new directory under `server/route-modules/` alongside `app-page`, `app-route`, `pages`, `pages-api`, plus a `RouteKind` entry in `server/route-kind.ts` and a definition in `server/route-definitions/`.
- Hosting platforms extend the build via `NextAdapter`: set `config.adapterPath` (or `NEXT_ADAPTER_PATH`) and export the adapter interface declared in `build/adapter/build-complete.ts`, which receives `AdapterOutput`/`AdapterOutputs` describing every emitted route including edge entries and their `handlerExport`.
- Cache backends plug in two ways: the legacy `CacheHandler` class contract (`get`/`set`/`revalidateTag`) consumed by `IncrementalCache`, and the newer `"use cache"` handler registry populated by `setCacheHandler(kind, handler)` / `initializeCacheHandlers(cacheMaxMemorySize)` with a documented stream-ownership contract.
- A tiered cache composition point already exists (`createTieredCacheHandler` returning a `CacheReadWriteHandler`), with dev-only maps at `Symbol.for('@next/cache-handlers-dev-tiered')` and `-dev-fronts` for layering an in-memory front over a remote handler.
- ESLint rules register in exactly one place: add the rule module under `packages/eslint-plugin-next/src/rules/`, import it in `src/index.ts`, and add entries to `plugin.rules` plus `recommendedRules` (and `coreWebVitalsRules` if it should escalate).
- The `@gate` condition registry in `test/lib/gate/conditions.ts` is a deliberate hand-written extension point — declare a `staticCondition` (available to `@force-gate`) or a `lazyCondition` reading the fixture's resolved config; referencing an undeclared name is a hard collection-time error.
- New test suites are scaffolded, not hand-written: `pnpm new-test --args <appDir> <name> <type>` runs a `turbo gen test` plop generator (types `e2e | production | development | unit`), and `pnpm new-error` generates an `errors/*.mdx` page the same way.
- Codemods extend via `packages/next-codemod/transforms/` with colocated `__testfixtures__` and `__tests__` directories, and are surfaced to users through `next upgrade`.
- Turbopack's Rust side extends through `#[turbo_tasks::function]` methods on `Project` / `ProjectContainer` in `crates/next-api/src/project.rs`, which are then exposed to JS by adding a napi binding and a corresponding method on `ProjectImpl` in `packages/next/src/build/swc/index.ts`.
- Bundled third-party deps extend through `packages/next/taskfile.js`: register `externals['pkg'] = 'next/dist/compiled/pkg'` and add an `ncc_pkg` task, which is what keeps `next` dependency-light at install time.
- Agent workflows are themselves an extension point: `.agents/skills/` holds 20 skill directories (`flags`, `dce-edge`, `react-vendoring`, `router-act`, `gate-tests`, `pr-status-triage`, `create-pr`, `backport-pr`, …) and `authoring-skills` documents the frontmatter spec and the AGENTS.md-vs-skill split.
- `create-next-app` extends through `packages/create-next-app/templates/`, driven by `create-app.ts`, so adding a starter variant is a template-directory change rather than CLI surgery.