tezvyn:

Kent C. Dodds Fixes Accidental Monorepo with Workspaces

AI-drafted, machine-checkedSource: Kent C. Dodds Blogintermediate
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.

Source: Kent C. Dodds Blog

Read the original → Kent C. Dodds Blog

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.