01 / Governance modelFederated, with a small core team
Every design system I've led runs on the same shape: a small core team owns the primitives, tokens, and the pipeline. Product feature teams contribute higher-order patterns and specialized components. Nobody has to route through the core team to ship — the contribution model is the path.
The tradeoff I've made every time: we optimize for enablement, not for control. If our system slows a product team down, they'll build around us. That's the failure state.
Principle
The smallest team that unblocks the most designers.
Core team headcount grows only when the pipeline breaks. Every new hire has to unblock more than they cost.
02 / Contribution flowFour gates, in order
Every contribution — from a token tweak to a new component — moves through the same four gates. The gates aren't approvals, they're conversations at the right level of detail.
Gate 1
Discussion. Open a GitHub Discussion. What are you trying to build? Does the system already cover it? If not, why not?
Gate 2
RFC. If the discussion warrants it, write an RFC using the template. Problem, options considered, recommended approach, migration story.
Gate 3
PR. Ship the code + Storybook stories + tests + a11y notes + Figma link. Every review uses the rubric in section 04.
Gate 4
Release. Land into the next minor version. Update the CHANGELOG. Announce in the design systems channel. Add to the office-hours agenda if it needs walkthroughs.
What we say yes to
- Patterns already used in 2+ product areas. A component earning its keep across surfaces graduates into the system.
- Fixes that improve accessibility, performance, or clarity. No gate 2 required. Straight to PR.
- Migrations that reduce debt. Especially if they retire an older pattern in the same PR.
What we push back on
- One-team patterns dressed up as system patterns. Not every good component belongs in the system. Sometimes the best answer is "keep it in your product library."
- New primitives when composition would do. If you can build it from Box + Stack + Text, you probably should.
- Additions that don't come with docs. If it's not documented, it doesn't exist — and it definitely doesn't ship.
03 / RFC templateMinimum viable proposal
The RFC template lives at .github/ISSUE_TEMPLATE/rfc.md in the repo. Five sections, none of them long:
What are we trying to solve? Who's blocked, and how often?
List at least two. Include "do nothing" if it's plausible.
The one we're proposing. Why this over the others.
How do existing consumers adopt this? Breaking or additive?
If breaking, what's the deprecation window?
The things we still don't know. Tag reviewers for each.
04 / PR review rubricFive checks, every time
Every PR gets reviewed against the same five checks. Reviewers leave inline comments tagged with the rubric letter so the author knows which check they're addressing.
A · API
Does the prop shape scale? Reads like English, composes with primitives, doesn't leak implementation. Deprecated props flagged.
T · Tokens
Are all values tokenized? No raw hex, no raw px. Semantic tokens preferred over primitives.
D · Docs
Is the docs entry complete? Usage, do/don't, prop reference, a11y notes, code + Figma links.
A · Accessibility
Does it meet WCAG 2.1 AA? Focus states, keyboard, semantics, reduced-motion. Screen-reader tested if novel.
M · Migration
Are consumers taken care of? Additive → nothing needed. Breaking → codemod or deprecation notice with a real window.
05 / Versioning + releaseSemver, but honest about it
Semver, applied strictly:
- Patch (x.y.Z): bug fixes, non-visual internal changes.
- Minor (x.Y.z): new components, new tokens, new props (all additive).
- Major (X.y.z): anything that could break a consumer. Batched, announced early, migration guide required.
Releases go out on a predictable cadence — weekly minor, monthly major review. Every release updates CHANGELOG.md using the Keep a Changelog format so consumers can diff by version.
06 / Deprecation policyLong windows, loud warnings
Nothing gets removed without a formal deprecation. The window is two major versions minimum. Consumers get:
- Runtime warning in dev mode with a link to the migration guide.
- ESLint rule (where applicable) that flags the deprecated import.
- Codemod when the migration is mechanical — most of the time it is.
- Announcement in the design systems channel, in the CHANGELOG, and in the next office hours.
Removing something before its window closes is a policy violation, not a judgment call. The whole point is predictability — teams should be able to plan.
07 / When governance breaks downThe escape hatches
Every governance model breaks at the edges. Here's what I do when it does.
Escape hatch 1
Product team needs to ship tomorrow.
Skip gates 1–2. Land the PR in the product's own library with a "system-candidate" tag. Backport into the system after the launch, following the full flow.
Escape hatch 2
Core team disagrees with a contributor.
The RFC gets a formal decision doc. Both positions written up, decision made explicitly, reasons recorded. Future contributors get the "why not" as much as the "why."
Escape hatch 3
System pattern isn't earning its keep.
Deprecation, but publicly. Explain what we tried, what we learned, what we're doing instead. Retiring a pattern well is as important as shipping one well.