UI Monorepo Strategy
Whether frontend code lives in one repository or many — a trade between atomic change and independent release.
Definition
A monorepo holds multiple projects in one repository with shared tooling and dependency versions. The alternative is a repository per project with published packages between them.
What a monorepo buys
- Atomic cross-project changes. Update a shared component and every consumer in one commit, with CI verifying all of them. This is the decisive benefit for shared design systems.
- One dependency version, eliminating the class of bug where two projects use incompatible versions of the same library.
- Shared tooling and configuration, so linting, formatting, testing and building are consistent.
- Discoverability, and easier refactoring across boundaries.
What it costs
- Tooling investment. Without task caching and affected-project detection, CI runs everything on every change and becomes unusably slow. This is not optional above a modest size.
- Coupling by convenience. Because reaching across a boundary is easy, it happens — unless boundaries are enforced by lint rules or build configuration.
- Coordinated upgrades. One dependency version means everyone upgrades together, which is a benefit and a constraint.
- Repository size, affecting clone times and some tooling.
- Access control granularity, which is coarser than per-repository.
The decision
Monorepo when projects share substantial code — a design system, shared utilities, common types — and the teams are within one organisation with aligned release cadence.
Multi-repo when projects are genuinely independent, when teams need independent release cadence, or when access must be restricted per project.
The hybrid is common and reasonable: a monorepo per domain or per team, with published packages between domains.
What must be built either way
- Enforced boundaries. In a monorepo, lint or build rules preventing cross-boundary imports. In multi-repo, the boundary is enforced by publication.
- Affected-project detection, so CI runs only what changed.
- Build caching, which is what makes a large monorepo viable at all.
- A clear ownership model — a code-owners file, so review routes correctly.
Interview question
"Ten frontend teams share a design system. Monorepo or separate repositories?"