Phase 02
pnpm Workspaces &
Dependency Boundaries
Workspace membership, the shared lockfile, strict dependencies, local
package linking, and where dependencies belong.
Book 3 - Workspace architecture
Course baseline: September 17, 2026 - Windows-first - Project-driven - Production-oriented
pnpm Workspaces and Dependency Boundaries
The root now exists. Before we add frameworks, we need to understand how pnpm decides what belongs to the
workspace and where dependencies should be installed.
The workspace file is a membership rule
pnpm-workspace.yaml sits at the root and defines package locations. The patterns apps/* and packages/* are
intentionally shallow: they match immediate package folders such as apps/web or packages/validators without
recursively pulling in arbitrary nested folders.
Workspace membership requires a package
A directory does not become a workspace package merely because it matches a glob. In practice it needs a
package.json. This distinction explains why an empty apps/ directory does not appear in pnpm recursive listings.
The shared lockfile
pnpm uses a single pnpm-lock.yaml at the workspace root by default. That makes dependency resolution reviewable
in one place and avoids one lockfile per application. The packages still declare their own dependencies; the lockfile
simply records the resolved graph for the workspace.
One workspace lockfile, separate dependency declarations
resolution resolution resolution
content-addressed files packages/validators
apps/web package.json apps/api package.json
package.json
Figure 1 - The lockfile is shared; dependency ownership remains package-specific
Root dependency or package dependency?
Dependency type Where it belongs Example
Frontend runtime/build apps/web react, next
dependency
Backend runtime/build apps/api @nestjs/core, fastify
dependency
Database dependency used by apps/api initially prisma, @prisma/client, pg
API
Shared library dependency the package that imports it zod inside validators, if that package
exists
Repository-wide developer tool root only when genuinely possible formatter/orchestrator later
cross-workspace
The -w flag is an explicit root decision
pnpm protects workspace roots from accidental dependency installation. If you intentionally add a root dependency,
use the workspace-root flag so the decision is visible:
Do not respond to an ERR_PNPM_ADDING_TO_ROOT warning by blindly adding -w. First ask whether the
dependency actually belongs to the root.
Package-specific installs later
Once apps/web exists, a dependency can be targeted without changing directories:
pnpm --filter <package-name> add <dependency>
Filtering becomes powerful in larger workspaces, but directory-local installation is also fine when it is clearer. The
goal is correct ownership, not clever commands.
The workspace: protocol
When one workspace package genuinely depends on another, pnpm supports the workspace: protocol. It
guarantees the dependency resolves to a local workspace package instead of silently falling back to a registry
package.
{
"dependencies": {
"@taskflow/validators": "workspace:*"
}
}
Not yet We do not create @taskflow/validators in Phase 02. This is a mental model for
later. The package will be introduced only when both web and API have real
validation reuse.
Strict dependencies are a feature
pnpm is intentionally strict about package access. A package should not rely on a dependency simply because
another workspace package installed it. This prevents hidden dependencies that work on one machine and fail when
isolated.
Why we are not adding Turborepo yet
Task orchestration tools become useful when several packages have real dev, build, lint and test scripts. Right now
there are no applications to orchestrate. pnpm already gives us workspaces, recursive execution and filters, so
introducing another tool would add vocabulary without solving a present problem.
Future, not forbidden Turborepo may become useful later for task graphs, caching and coordinated
builds. The teaching rule is not "never use Turbo"; it is "earn the abstraction
when the repository has enough work to orchestrate."
Version pins operate at different layers
File/field What it communicates
.node-version The exact Node version fnm should select for this repository.
engines.node The Node compatibility range expected by the package.
packageManager The pnpm version the repository expects.
Volume 01 - Engineering Foundation
File/field What it communicates
pnpm-lock.yaml The exact resolved dependency graph.
Dependency-boundary checkpoint
•
You can decide whether a dependency belongs to the root, web, API, or a future shared package.
•
You understand that one lockfile does not mean one package.json.
•
You know what workspace:* guarantees for local dependencies.
•
You will not create a shared package until at least two consumers need the same responsibility.
•
You know why root-install warnings should trigger reasoning rather than automatic flags.
Volume 01 - Engineering Foundation