Easy to launch. Hard to keep.
Nine products, one design system, and the two migrations it took to make it survive.
- Role
- Design system lead
- Company
- Sprout Solutions · HRIS
- Timeline
- 2022 – 2026
- Team
- Design + frontend, every product
Open the Storybook- products
- 9
- years
- 4
- migrations
- 2
Getting it adopted
A system is easy to launch. Getting nine products onto it, without asking anyone to stop shipping, is the whole job.
Final_Final_UseThisOne
I moved to another product team and opened their Figma. Final_V2. Final_Final_UseThisOne.
The files weren't the problem. Nobody could tell which one was true.
Nine dialects of the same UI
Ten years of building on top of what was already there. Customers moved from HR to payroll to the full suite and felt every seam — same brand, different rules.
Every one of these was a reasonable local decision. Nine reasonable local decisions don't add up to one product.
Foundational styles, components, governance
Three layers, in order. Foundational styles: one definition of color, type, spacing, radius — any designer proposes a change, the whole design team reviews it. Components built on top, documented in Storybook.
Then governance, which is the layer that actually decides whether a design system survives. Teams don't request components here. They contribute them — needing one is how you end up owning one, alongside the roadmap rather than instead of it.
- Sprint needa team needs a component
- Check the systemdoes it already exist?
- Check the boardnot listed · backlog · in progress · done
- Design reviewspecs written if the design isn't ready
- The team builds itinto the system, alongside their roadmap
- Code + design reviewboth, every time
- Deploy to the systemeveryone gets it
The migration nobody had to stop for
No freeze, no rewrite. Teams upgraded a screen when they already had it open. Slower than a rewrite, and the reason it survived real deadlines.
Designers can't adopt what they can't find. We cleaned the room before building anything.
What broke
Happy path documented early, ugly states late. One-offs filled the gap and some are still there.
People reached for the familiar pattern long after the component existed. Docs didn't fix it; pairing did.
Every conversation restarted from zero until there was a migrated screen to point at.
Where it stood
One foundational-style layer, one component library, public docs, and nine products that finally looked like one company.
- Coverage
- 87%component coverage
- Sources
- 9 → 1sources of truth
- Adoption
- 3 qtrto adoption
Getting it adoptable
A year later the system was fine and the way we shipped it was the problem.
It held for a year.
Then the thing that made the system easy to distribute made it impossible to change.
The system was never the problem. The package was.
Version drift
Every product pinned a version and stopped upgrading. Releases became ceremonies. A year in, we had the 2022 problem again — this time wearing a package.json.
- Product A@design-system: 1.2.014 releases behind
- Product B@design-system: 2.0.36 releases behind
- Product C@design-system: 2.4.1current
Nobody could change it
The components lived in another repo. That made the same thing impossible for two very different consumers — a team that needed one hover state, and an agent that couldn't read the source at all.
- Patch the third-party library
- Re-verify with the other teams
- Deploy to the production design system
- Now the team can use it
- Sees node_modules — opaque
- Reads the .md docs instead
- Matches the look, invents the code
Prose documentation isn't runnable code. The agent matched the look and invented the implementation.
The second migration
We piloted the shadcn model on one product — Agentic Implementation — then broke from the package. Adoption was fast because everyone could already see the old model wasn't sustainable.
Source lands in the repo; foundational styles stay the contract. Teams own the file, agents read the real rules, and a needed variant stops being a fork.
- Run it▸ add choiceboxsource redacted
- It drops a filecomponents/ui/choicebox.tsxyours now — editable, reviewable, diffable
- It reads your stylesSame component, re-skinned by foundational styles alone.the prototypes on this site are the proof
Proof: one prompt, a real screen
The argument for moving off our published component library was hard to make in a deck. So we built the same screen twice and watched an agent try to help.
Click between the two models. Same prompt, same screen — the only variable is how much of the system the agent can read.
| Employee | Net pay | Status | |
|---|---|---|---|
| A. Ramos | ₱48,200 | OT | |
| J. Villamor | ₱52,900 | ND | |
| M. Cruz | ₱41,150 | OK | |
| R. Santos | ₱39,700 | OK | |
| Total | ₱6.1M |
That was the argument. Not that one model is nicer — our components had to be readable by the thing writing most of our screens.
What broke
A fix in the canonical component no longer reaches every product on its own. Someone has to re-pull or diff.
Literal cards used for single-select, where the choicebox already exists. Freedom to edit isn't knowledge of the system.
Agents edit freely, so borders thicken and card radii stop matching. Small, constant, everywhere.
The freedom that let agents work is the same freedom that lets them drift. Governance now has to catch what a version number used to.
Where it stands
Foundational styles are the contract, the registry can diff a copied component against upstream on demand, and Storybook is what keeps behaviour consistent across repos. The rest of the drift problem is open.
What's different is what a screen costs now. An agent reads the real components and the real styles, so what it generates is on-system by default instead of a lookalike someone has to unpick.
What I'd do differently
- Write the migration guide first, not last.
- Document the ugly states early — empty, loading, error, too-long label.
- Stop selling. One migrated screen convinced more people than a year of explaining.
- Ship the lint rules with the freedom. Copy-in without a token check is an invitation to drift.
- Treat the registry as a product, with a changelog teams can read and a diff they can run.
- Teach the pattern, not the component. A team that knows why the choicebox exists won't reach for a card.
Foundational styles, every component, and the states teams actually ship — the same library the nine products read from.