Kent C. Dodds Fixes Accidental Monorepo with Workspaces
Kent C. Dodds consolidated four deployable apps into a proper npm workspace, deleting three nested lockfiles and adding minimal Nx caching. The migration exposed hardcoded paths and invalid package aliases that broke production once Node enforced package…
Why it matters
Most repos with multiple deployables are accidental monorepos. Kent C. Dodds had four runnable systems in one git repo, each with its own package.json, lockfile, and tsconfig, but no actual workspace structure. This pattern is common in real production codebases and it creates silent coupling. Paths, imports, and build assumptions drift until a folder move breaks production. Formalizing the monorepo forces Node to enforce package boundaries, which surfaces hidden dependencies immediately.
What changed
Dodds moved every runnable thing under services/* and converted the root package.json into a thin orchestration layer. The site, an OAuth Cloudflare Worker, an audio worker, and a Docker audio container each got their own workspace package. Three nested lockfiles were deleted and replaced by one root package-lock.json, which accounted for most of the 726 file diff. Nx 22.5.4 was added with a minimal nx.json that enables caching for build, lint, typecheck, and test targets through package-script inference alone. No hand-authored project.json files were required. The real application scripts like ci:verify and test:browser stayed inside services/site/package.json where they belong.
The migration broke production in two specific ways. First, an import alias referencing other paths failed because it resolved to directories outside the new services/site package boundary, triggering ERR_INVALID_PACKAGE_TARGET. These were replaced with explicit relative paths. Second, a hardcoded content path prefix used to fetch MDX files from GitHub at runtime pointed to the wrong location after the move, causing an outage.
What to watch
If you are running multiple apps from one repo without a workspace declaration, you are likely coupled in ways you cannot see yet. The services/* constraint is a useful rule: every deployable gets its own package boundary. You do not need heavy Nx plugins to get value; inferred caching and a single lockfile are enough to start. Watch for hardcoded paths and alias configurations that assume a specific root-relative layout. Those are the first things to break when Node starts enforcing package boundaries.
Interview question
Why did moving the apps into workspace packages under services/* initially break production?
- a.The root package.json orchestration layer masked environment variables required by the OAuth worker at runtime
- b.Nx build caching invalidated Docker layer caches and caused container startup failures
- c.Node enforced package boundaries, exposing invalid import aliases and hardcoded paths that assumed the old root-relative layoutCorrect
- d.Consolidating three lockfiles into one root package-lock.json introduced conflicting transitive dependency versions
Why? this is the answer
Node began enforcing package boundaries after the move, so an import alias that reached outside the services/site boundary failed with ERR_INVALID_PACKAGE_TARGET and a hardcoded MDX fetch path pointed to the wrong location. Option D is tempting because lockfile consolidation produced most of the diff, but the outage was caused by path assumptions, not dependency conflicts.
Just read this? Test yourself on what you have been reading.
Read the original → kentcdodds.com
- #monorepo
- #npm workspaces
- #nx
- #node.js
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles