Monorepos (Turborepo / Nx / pnpm workspaces)
One repo for multiple packages. Useful when they evolve together; painful when they shouldn't.
1 credit
Why bother
- Shared code (UI kit, utils) without publishing to npm.
- Atomic changes across apps + libs in one PR.
- Unified lint / typecheck / test config.
- Dependency graph enables smart caching — only rebuild what changed.
The players
5 itemspnpm workspaces
Just a package manager feature. Free, minimal. Start here.npm / yarn workspaces
Same idea, worse hoisting. pnpm is strictly better.Turborepo
Task runner + remote cache. Zero config to add. Great for Vercel-hosted.Nx
More opinionated. Graph, generators, cloud cache. Heavier but more features.Bazel / Buck
Monorepos at Google/FB scale. Massive setup cost. Not for teams <50.Minimal pnpm workspace
text
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
# Folder layout
apps/
web/ # Next.js app
docs/ # another app
packages/
ui/ # shared UI components
utils/ # shared helpers
# In apps/web/package.json
"dependencies": { "@acme/ui": "workspace:*" }Gotchas
- Package boundaries matter — circular deps between packages are allowed by bundlers but cause headaches later.
- Version skew — if `@acme/ui` needs React 19 and `apps/web` pins 18, you'll see duplicated React in node_modules.
- CI cost explodes without caching — rebuilding every package on every push is slow. Use Turbo/Nx remote cache.
- Don't monorepo things that shouldn't move together. Independent release cycles → separate repos.