Modularization and package management
pnpm workspace is an interesting way to do things. It formalizes each subdirectory into a program module under unified management, so that each module exists as a package you can bring in through the @xxx/xxx form. This architecture of gathering several modules in one repo is called a monorepo, and the good thing about it is all in one, everything managed together, without having to jump around between several repos (or scattered folders, which are logically similar to repos). It’s much more convenient for maintenance and version control.
Say it used to be
backend/ ← the backend, has its own package.json
frontend/ ← the frontend, has its own package.json
shared/ ← shared types (kept in sync with frontend by hand-copying)
and with pnpm workspace you can turn the whole project into
project/
├── pnpm-workspace.yaml ← new: declares packages/* as workspace members
└── packages/
├── backend/ ← the old backend
├── frontend/
└── shared/ ← becomes a real package: @editorial/shared
This is very convenient when the same types or contracts have to be shared across modules. The old separated-folder form still needed you to cross-check by hand, and over time it drifts very easily, relative paths especially — once the structure needs adjusting later, basically the whole codebase has to change. So the simplest and tidiest way is to abstract it into a package and hand it to the package manager to allocate. If it needs adjusting or extending later, you just carry on from there, which is very convenient.
There’s also dependency management, where all the modules’ dependencies can be managed together instead of each writing its own. For supply chain security and for whatever soundness you get out of it, that’s much better than scattering them inside each one. For programming in the ai era, compared with using “microservices” to isolate repos the way I mentioned in Process-based quality control, a monorepo costs a bit less. On operations especially, standing up a k8s is still too much of a burden. Overall, lightweight modularization approaches like micro-frontends or monorepos are the form I prefer.
But the biggest advantage of the ai era is “code abundance”, and architecture is gradually starting to beat pure “code volume”. In the past an engineer might have given up a clear and isolated architecture because the coding cost was too high, since the overall maintenance and development cost would go up. But today, development cost in the ai era is compressed to the extreme, and it’s maintenance cost that’s becoming the short board instead. At that point the advantage of a clear architecture wins out — code that tests well, holds up and is loosely coupled is far easier to maintain than sprawling code. Especially for ai development: rather than letting it swim around inside unnameable spaghetti where one change collapses the whole thing, better to let it move in order between clear, well-bounded islands. At least with the latter, even when a problem shows up, its boundary can be held strictly inside the island; with the former, the chain reaction could bring on a caving, total collapse. On holding up under pressure, the islands clearly win.
Translation note. I wrote this in Chinese. This English version is an LLM translation, so the wording is not mine even though the thinking is. Original: 模块化和包管理.