Background
Fulling currently pins pnpm@10.20.0 and invokes it through Corepack. For the current single-package Next.js application, this additional package-manager bootstrap is spread across:
package.json: packageManager, engines.pnpm, and pnpm.overrides
Dockerfile: two corepack enable / prepare sequences
- GitHub Actions:
pnpm/action-setup and PNPM_VERSION
README.md, CONTRIBUTING.md, and AGENTS.md: every command uses corepack pnpm ...
pnpm-lock.yaml
The project is not currently a workspace or monorepo and does not use pnpm-specific features such as catalogs, patches, or filters.
Decision
Migrate to npm and keep Node.js as the only runtime.
The goal is not to optimize for the fastest possible dependency installation. It is to reduce toolchain complexity across contributor onboarding, local development, CI, and container builds:
- npm is installed with Node.js, so contributors do not need to install or activate an additional package manager.
- Corepack is still marked Experimental and is no longer distributed with Node.js starting in Node.js 25. Continuing to make it the default entry point creates future upgrade work.
npm ci fails when the lockfile and package.json are out of sync, which meets our reproducible-install requirements for CI and containers.
- npm supports root-level
overrides, so the current pnpm.overrides configuration can be migrated directly.
- npm supports workspaces, so a future move to a monorepo would not immediately invalidate this decision.
- Next.js officially supports npm, pnpm, Yarn, and Bun; the framework does not require pnpm.
Alternatives considered
| Option |
Assessment |
| Keep pnpm but remove Corepack |
Viable, but pnpm would still need to be installed and versioned separately. This removes Corepack without simplifying the overall bootstrap. |
| Yarn |
Not recommended. Yarn's official installation flow still starts with installing Corepack, so it does not address the underlying concern. |
| Bun |
Not recommended for now. Its installation speed and automatic pnpm lockfile migration are attractive, but it still introduces another executable that must be installed and pinned. Its dependency lifecycle-script behavior also differs from npm and pnpm, requiring additional validation for Prisma, Next.js native dependencies, and Playwright. The current project size does not justify that maintenance cost. |
| npm |
Recommended. It may not offer the fastest installs, but it provides the lowest toolchain and onboarding cost for the current single-package application. |
Migration scope
Acceptance criteria
References
Background
Fulling currently pins
pnpm@10.20.0and invokes it through Corepack. For the current single-package Next.js application, this additional package-manager bootstrap is spread across:package.json:packageManager,engines.pnpm, andpnpm.overridesDockerfile: twocorepack enable / preparesequencespnpm/action-setupandPNPM_VERSIONREADME.md,CONTRIBUTING.md, andAGENTS.md: every command usescorepack pnpm ...pnpm-lock.yamlThe project is not currently a workspace or monorepo and does not use pnpm-specific features such as catalogs, patches, or filters.
Decision
Migrate to npm and keep Node.js as the only runtime.
The goal is not to optimize for the fastest possible dependency installation. It is to reduce toolchain complexity across contributor onboarding, local development, CI, and container builds:
npm cifails when the lockfile andpackage.jsonare out of sync, which meets our reproducible-install requirements for CI and containers.overrides, so the currentpnpm.overridesconfiguration can be migrated directly.Alternatives considered
Migration scope
pnpm.overridesto root-leveloverridespackageManager: pnpm@...andengines.pnpm; document the supported Node.js/npm version policypackage-lock.json, then removepnpm-lock.yamlpnpm/action-setupandPNPM_VERSIONactions/setup-nodecache tonpmnpm ci,npm run ..., andnpm exec ...npm ci --ignore-scriptsnpm execREADME.md,CONTRIBUTING.md, andAGENTS.mdAcceptance criteria
npm cinpm run lintpassesnpm testpassesnpm run test:e2epassesnpm run buildpassesReferences