Six brands, one design system, six repositories
How a company with one engineer runs six production products without the shared code turning into a single point of failure.
There are six MadCool products in production. Marketing software for specialty audio dealers. A digital-shelf control plane for premium audio brands. Voice-matched social publishing. An independent AI hardware publication. A markets dashboard. A browser game studio.
They share a design system, a hosting platform and a database vendor. They do not share a repository, and that turns out to be the decision everything else rests on.
The obvious architecture is wrong
The obvious move is one monorepo. Six apps, shared packages, one install, one lint gate, one place to change a token. It is what every guide recommends and it is what the first version of this network actually did.
It fails on a detail that no guide mentions: build slots.
Our hosting team has one concurrent build. A monorepo means every pull request on any product queues a preview deployment, and the busiest product spawns two of them. In practice a change to the game studio waited an hour behind a marketing deploy it had nothing to do with. The coupling was not in the code. It was in the queue.
So the network is six repositories with six projects, and a change to one cannot make another wait.
What is actually shared
Three things, and the list is short on purpose.
The design tokens: ground, foreground, muted, a hairline, and one accent per brand. Every product defines the same custom properties with the same values. They are copied, not imported.
The interaction language: each brand has a motion character that means something. Audio clears noise and releases signal. Social broadcasts outward and draws followers back. Money settles into place, the way a number does when it stops moving.
The planet: each brand is a mineral world. Blue agate, jade, cobalt sodalite, amethyst, terraced basalt, and banded marble for the infrastructure layer.
Copying is not a failure
Copying tokens sounds like the thing you are supposed to avoid. Here it is deliberate, and the reasoning is about blast radius rather than about elegance.
A shared package means one bad publish breaks six production sites at once. Copied values mean a mistake breaks one site, loudly, in the repository where somebody is already looking. The cost is that changing a token means six commits. That happens perhaps twice a year, and each one is a two-line diff.
The guard against drift is a test rather than a package. Each repository asserts that its token values match the ones its brand is supposed to have. Change the hex in one place and forget the other, and the build fails in the repository where you made the change.
Where it actually breaks
Two places, both worth knowing before copying this.
Anything with a schema. Tokens copy fine because they are values. A database schema does not, because two copies drift into genuine incompatibility and you find out during a migration. Products that share data share one project and one schema, and the tenancy is enforced in rows rather than in repositories.
The pieces that carry real behaviour. A focus trap, a consent cookie parser, a rate limiter: copy those and you get six subtly different bugs. The rule we landed on is that a thing gets extracted into a package the moment a bug in it would be a bug in all six copies. Values copy. Behaviour does not.
That line is not obvious in advance, and we have moved it in both directions more than once.