Turning a product that brands fork into a system that brands configure.

One travel-benefits platform. Multiple partner brands: card networks, banks and insurers, each needing the product to feel entirely their own. Atom is the design system that makes that cheap. One component layer, themed per partner, where every new brand is a configuration exercise rather than a rebuild. The first launch on the model shipped with 89% less delivery effort.

Scope

Token architecture, component library, brand theming, accessibility, governance, tooling

Stack

Figma (variables, modes), Storybook, Jira, Claude + Figma MCP

40+

components

650+

variants

897

live variables

7

brand modes

3

breakpoint modes

89%

less launch effort

40+

components

650+

variants

897

live variables

7

brand modes

3

breakpoint modes

89%

less launch effort

40+

components

650+

variants

897

live variables

7

brand modes

3

breakpoint modes

89%

less launch effort

Why Atom was built

One product has to be many products at once.

Dragonpass delivers airport-lounge and travel benefits on behalf of partner brands, and those partners set a high bar for visibility: a cardholder opening the product from their bank's app should never feel they have left the bank. Every partner is a full product identity, with its own colour, type, spacing and corner radius, sitting on the same flows and the same components.

When I joined in May 2025, nothing underneath made that cheap. Each brand was a fork, each launch a rebuild, and with the whole product-experience group about to start consuming the responsive product, the cost of every new brand was set to compound. Atom exists to invert that: keep the product one product, and make brands a switch you flip.

One layer, themed per partner (sample design)

Why Atom was built

One product has to be many products at once.

Dragonpass delivers airport-lounge and travel benefits on behalf of partner brands, and those partners set a high bar for invisibility: a cardholder opening the product from their bank's app should never feel they have left the bank. Every partner is a full product identity, with its own colour, type, spacing and corner radius, sitting on the same flows and the same components.

When I joined in May 2025, nothing underneath made that cheap. Each brand was a fork, each launch a rebuild, and with the whole product-experience group about to start consuming the responsive product, the cost of every new brand was set to compound. Atom exists to invert that: keep the product one product, and make brands a switch you flip.

IMG 02

A simple diagram. One product core fanning out to seven brand endpoints, labelled "one product" on the left and "seven brands" on the right. Schematic, not a screenshot. Caption: The business model, drawn: one product, worn seven ways.

Design and code, disagreeing about the same component.

The state before Atom

Every brand had its own design system. That was the problem.

The state before Atom was not a lack of a design system. There were several. Each partner brand ran on its own separate system: its own components, its own colours, its own files, maintained in parallel by hand. Nothing was shared, so nothing was inherited. A fix made in one brand's system stayed in that brand's system, and the estates drifted further apart with every release.

The cost landed hardest whenever a new client came through. Onboarding a brand meant heavy, duplicated work: standing up yet another system from scratch, detaching screens and rebuilding them by hand, recreating components that already existed elsewhere with slightly different values. On one partner pitch, roughly two months of that work was compressed into two weeks. Every new client added cost; nothing amortised it. Atom was built as a single multi-brand system precisely to replace many single-brand ones.

The drift showed everywhere the parallel systems touched. Two codebases, web and mobile, for most modules. Token changes had no pipeline, so a single rename meant manual edits and a QA pass in four codebases. Design and code disagreed on the names of the same things: "accordion" in design was "collapse" in code, "checkout" was "pay card", and some components existed in engineering with no design reference at all. Three status labels, error, danger and destructive, coexisted for two concepts. One module had no responsive version, another's desktop design was a straight copy of mobile, a third missed tablet breakpoints.

And the consolidation had to happen on a shipped product. Screens had been designed, client-approved and built long before any shared foundation existed, so the standard could not be defined and rolled out; it had to be reverse-engineered from live UI I was not allowed to visually change, with colours on no logical ramp and, thanks to the mobile-first legacy, basic desktop states, input hover for one, that had never been created.

Four constraints fell out of this starting position. The UI was client-approved, so I could change what things were made of but not how they looked. Multi-brand requirements invalidate single-brand rules: button radius is unique per brand, so one radius token does not survive this product. Desktop states had to be created retroactively. And I was the sole maintainer, so every quality check had to run without me policing it.

The architecture

Three Figma libraries in strict dependency order.

Atom Design System: multibrand design system architecture

Three tier architecture

The Primitives Library hold the raw material: colour ramps from 50 to 950. The Brand Switcher holds the semantic layer and the brand modes, the single layer engineering consumes. The component library builds everything against Brand Switcher tokens, never raw values. Toggle a brand mode and colour, type, spacing and corner radius all swap: one component layer, themed per partner.

The live Brand Switcher today: a Theme collection of 183 semantic tokens across seven brand modes; 686 breakpoint variables across three modes — Mobile/App, Tablet, Desktop; dedicated Semantic Spacing, Radius and Border collections; 897 variables in all. Even the grid is tokenised: responsive/margin, gutter, canvas, column — engineers count columns, never hardcode pixels.

Client configuration splits by client type: channel partners configure at the primitive level; white-label clients touch semantic tokens only, supplying as little as a primary and a highlight. The principle underneath: the system’s tokens stay stable and white-label configuration adapts to them, never the reverse.

The semantic layer engineering consumes.

Try it

Don’t take my word for it. Switch a brand.

Three components from the library, running on Atom’s real token values and real component specs, down to the regular weight button label.

Atom Design System

One system. Three brands.

TypePoppinsRadius999Action#0A2333Stroke1px
Button
Input
Label
Helper Text
Accordion

Decisions

Decisions that shaped it.

Naming is a contract.

My standard is an exact 1:1 between Figma and codebase — any developer should map code to the design system instantly. Where the two disagreed we picked the industry-standard term, validated against Ant Design and Material: “accordion” beat the inherited “collapse”. Inside components the same discipline holds — type for semantic values, state for interactive states, style for visual variants — because a property named state holding “success” is a future bug in someone’s head.

Three labels became two.

Error, danger and destructive coexisted for overlapping concepts. We consolidated: danger is the semantic token — red means more than system faults — and destructive survives only for destructive button actions. The live token set carries it end to end, from border/status/danger through background/interactive/danger-pressed to a new foreground/status/danger for informational red. Zero error tokens remain in the semantic layer.

The argument I lost — and wrote down.

I wanted every colour defined once in primitives with semantics pointing at variables, the way Ant does it. Engineering defines most colours as raw hex directly in semantic tokens, because a black button with a blue hover can’t derive from a standard ramp, and white-label clients should only ever supply two values. Their approach shipped. My job then wasn’t to keep relitigating — it was to record the decision so the debate stops resurfacing, and keep the trade-off visible. Systems work is knowing which arguments to close.

A structural rename that cost engineering nothing.

Consolidating action into interactive was executed as a structural rename, not a rebuild — zero components recreated in code. The entire interactive token family now lives under that group. A migration absorbed for free is an architecture win, and I count it as one.

Radius and behaviour became semantic because brands diverge.

Radius moved from per-component values to a semantic scale plus brand-scoped component tokens — components/button/radius exists precisely because button radius is brand-unique. The progress indicator, which once varied per brand with no rationale, is now governed by its own tokens: height, radius, active colour.

Guidelines before enforcement.

Spacing standardised on an 8px rhythm — including an audit walking stray 10px gaps back to 8 — but documented as guidance before being enforced as tokens; multi-brand constraints punish over-engineered rules. The same judgment shows up smaller: slots were added without removing the controlled variants designers rely on, and checkbox, radio and check-indicator were split into three component sets because merging them confused their use cases.

IMG 04

A changelog entry for the danger or interactive migration.

Every token change recorded — what, why, and where.

Accessibility

Accessibility as architecture, not review.

Accessibility in Atom is a first-class layer with an explicit ownership split: contrast and visual states are design’s; keyboard navigation and ARIA are engineering’s. The standard is WCAG 2.2, and the rules are concrete — a 24px minimum clickable area (I rejected a 12px close icon over it), focus rings on every interactive component including the desktop breadcrumbs where they were missing, contrast measured against the immediate surface a component sits on. One deliberate, documented exception: disabled states are excluded by design, not oversight.

Because I won’t scale a standard through review meetings, I built the checking into a tool: a custom Figma plugin mapped to WCAG 2.2 that audits components per state. And I ship it with its own test harness — an A11y Test Sheet of deliberately broken components with expected results documented, so anyone can verify the auditor catches what it claims to catch. I validated it against an established community plugin before trusting it myself.

IMG 05

The accessibility plugin flagging a deliberately broken button on its own test sheet.

The auditor, audited.

Governance

Governance that runs itself.

Every release is versioned and documented on changelog pages in both libraries — Atom 1.0, Atom 1.1, dated token-change entries — alongside a Token Table reference, so handover needs no re-explanation. Work-in-progress lives under bracketed namespaces so live designer files are never polluted, and “ready for dev” is treated as a promise: the label comes off anything unfinished. I published the same instinct publicly as Changelog Tracker, my Figma community plugin.

The library itself is organised for governance: core components grouped by type — actions, system feedback, data display, data entry, layout, navigation — then patterns, with a component index and documentation index as entry points. A dedicated taxonomy workstream with front-end aligned names, colours and tokens on both sides, and a Storybook layer gives design and engineering one shared surface. Documentation is generated, not hand-written: a Claude Code + Figma MCP pipeline reads the Brand Switcher and the library and produces a browsable docs site, component by component, brand switcher included.

IMG 06

Changelog Tracker’s Figma Community listing.

The governance instinct, published as a public plugin.

IMG 07

A component page in the generated docs site, mid brand-switch.

Documentation generated from the source of truth.

Tooling

AI is the system’s maintenance crew, not its designer.

Agentic workflows over the Figma MCP audit the gap between design and code — missing tokens, mismatched names, undocumented variants. Documentation, specs and change history are generated. The accessibility pass is a plugin, not a meeting. The judgment calls — what to name things, which arguments to close, what a brand may configure — stay human.

Proof in production

115 man-days versus 12.5.

Two channels launched toward the same destination. One was built the traditional, bespoke way. The other ran on Atom’s reuse model. The gap is the whole case for the system.

115

man-days — traditional bespoke build. Backend 55 · Android 21 · iOS 21 · HS 18

12.5

man-days — Atom reuse model. Frontend integration 6 · backend support 6.5

13

man-days — next channel on the same model, even as a high-customisation build

That is 89% less delivery effort — roughly 102 man-days given back on a single launch. And it wasn’t a one-off: the next channel on the same model came in at 13 man-days even as a high-customisation build — the pattern held.

The timeline told the same story in calendar form: the reuse-model channel started roughly three months later and still launched first — six days ahead of the traditional build.

IMG 08

The delivery comparison from my impact slides: two timelines, and the 115 / 12.5 / 13 man-day bars.

Same destination, one tenth of the effort.

Adoption

Adoption was the real design problem.

A system only works if people trust it. I ran one-to-one sessions with every designer to show Atom in practice, then a group share-and-learn tying it back to the business goal — every designer on the team is onboarded. I worked shoulder-to-shoulder with engineering, adjusting Atom where it genuinely needed to flex rather than defending it rigidly. And I led with evidence: documenting the delivery numbers turned Atom from a design initiative into a proven business tool — leadership’s own framing was that the data showed improved efficiency and cost reduction, a new way of delivering work.

The recognition that stuck with me came from the people using it: a product lead’s shout-out for jumping on a live call to solve an icon issue before it became everyone’s rework; kudos for bringing a stream of new components to life; a plain “high five all round” on Atom itself.

Outcomes

What the system delivered.

  • An 89% reduction in launch effort on the reuse model — roughly 102 man-days saved on the first launch alone, with the next channel confirming the pattern at 13.

  • A later start beaten by a faster ship.

  • Seven brand modes served from one component layer of 40+ components and 650+ variants, driven by 897 live variables across three breakpoint modes.

  • A semantic layer that got leaner as brands were added — 313 theme variables serving six brands in spring became 183 serving seven by late summer.

  • A structural token migration absorbed by engineering with zero rebuild.

  • Three status vocabularies consolidated to two.

  • An accessibility standard that checks itself.

  • A duplicated-code reduction of over 60% as squads converged on shared components.