A pnpm workspace lets you manage multiple packages in a single repository. Adding Nx to a pnpm workspace gives you cached tasks, affected-only builds, and faster CI, while pnpm keeps managing installs. This recipe sets up a pnpm workspace and then adds Nx.
Set up a pnpm workspace
Section titled “Set up a pnpm workspace”A pnpm workspace is a repository whose root contains a pnpm-workspace.yaml file. Its packages field tells pnpm which directories hold package.json files:
packages: - 'apps/*' - 'packages/*'A common layout separates applications from shared packages:
Directorymy-workspace/
Directoryapps/
Directoryweb/
- package.json
Directorypackages/
Directoryshared-ui/
- package.json
- package.json
- pnpm-workspace.yaml
To depend on another package in the workspace, reference it with the workspace: protocol so pnpm resolves it to the local package:
{ "name": "web", "dependencies": { "react": "^19.0.0", "@my-workspace/shared-ui": "workspace:*", },}Run pnpm install once at the root to install every package's dependencies and link the internal ones.
Add Nx in one command
Section titled “Add Nx in one command”Nx layers task running and caching on top of your existing pnpm workspace. pnpm still installs and resolves packages; Nx makes your tasks cacheable and your CI affected-aware. Add it with one command, which works on any npm, Yarn, pnpm, or Bun workspace:
npx nx@latest initYour existing package.json scripts keep working. Nx infers a project for each package.json in your workspace and runs its scripts with caching, with no project.json or extra configuration required.
Run tasks before and after Nx
Section titled “Run tasks before and after Nx”Before Nx, pnpm runs a script across packages, but it runs every task every time and has no notion of which packages a change affects:
pnpm -r run build # every packagepnpm --filter web run build # a single packageAfter nx init, run the same scripts through Nx:
nx run-many -t build # every projectnx build web # a single projectnx affected -t build # only projects touched by your changesThe first run executes your scripts. A second run with no changes is restored from the cache instantly, and nx affected skips the projects your change does not touch.
How task caching works
Section titled “How task caching works”nx init writes an nx.json with targetDefaults that control which targets are cached:
{ "targetDefaults": { "build": { "cache": true, "dependsOn": ["^build"], }, },}cache: true makes a target cacheable: Nx hashes each project's inputs (source files, dependencies, and config) and restores its outputs from the cache when nothing has changed. dependsOn: ["^build"] builds a project's dependencies first. Nothing is cached unless you opt in, so you stay in control.
In CI, turn on remote caching and task distribution to share the cache across machines and parallelize tasks. For a deeper walkthrough, see Adding Nx to an NPM/Yarn/PNPM Workspace or the From pnpm Workspaces to Distributed CI course.