The work behind the work
Royal London Design System
Token architecture, a design-to-code pipeline, and the harder problem of adoption at scale.
- Role
- Lead Front-End Design Engineer, then Technical Specialist (Web Development)
- Team
- 6 people (2 engineers)
- Scope
- Token architecture, design-to-code pipeline, grid system, icon library, adoption
-
4 → 9From 4 to 9
product teams on the system
15 to 20 expected by the end of the year.
-
~1,000Around 1,000
tokens across 3 tiers
Primitive, semantic and component.
Design systems rarely struggle because someone made a bad call. Small teams move fast, requirements grow, and nobody gets time to go back and fix the early work. What worked well for four teams looks different at nine. What works at nine will need revisiting at twenty.
No dig intended. That’s what delivery pressure does to a small team. Royal London’s was no different.
The system I inherited
When I joined, the design system was doing its job well. Components were in use across four product teams. It had a token layer, a grid and icons, and all of it was holding up.
But it had been built for four teams, and a lot more were on the way.
The token layer had no direct connection to Figma. Designers worked in one world, engineers in another, and keeping them aligned required manual effort that didn’t always happen. Values and names drifted until the product no longer matched the system.
The grid was class-heavy in the way grids were before CSS Grid had broad support, a Bootstrap-influenced approach with modifier classes for every breakpoint and column width. It worked, but the markup was noisy, and you couldn’t tell what a layout was for from its string of classes.
The icons were font-based. Fast to implement at the time. Not good enough now on accessibility or performance.
None of it was broken. But all of it had a better version.
What we built
A token architecture with a real pipeline
The first priority was closing the gap between design and code. That meant new tokens and a process to keep them current.
The new architecture has three layers: primitives (raw values: colour, spacing, typography), semantic tokens (mapping intent to those primitives), and component-level tokens scoped to specific patterns. Around 1,000 tokens in total, each named on purpose and traceable to a decision.
The pipeline runs from Figma variables through Style Dictionary, managed via Azure DevOps. A designer publishes a change in Figma. The import job picks it up, Style Dictionary transforms it, and publishes a new package. Developer review is a deliberate gate. It catches anything unintended before it ships. The goal is a Figma publish webhook that triggers the full pipeline automatically. We’re not there yet, but it beats syncing by hand.
A grid built on CSS Grid and data attributes
The old grid expressed layout through class combinations. A layout item at a given breakpoint looked something like this:
<div class="rl-l-grid">
<div class="rl-l-grid__item--xsmall-xx rl-l-grid__item-lg-xx">
The new grid uses native CSS Grid and data attributes:
<div class="rl-l-grid">
<div class="rl-l-grid__item" data-span="4">
The markup is quieter and easier to read. We moved from flexbox to CSS Grid because browser support had caught up and there was no reason left to hold off, and the data-attribute approach says what the layout is without stuffing the class list.
Icons as an SVG sprite
The font-based icon approach had two problems we could no longer ignore: accessibility and performance. Font icons arrive as a single character in the accessibility tree. Screen readers handle that inconsistently at best. They also carry the weight of the entire font file regardless of how many icons you’re actually using.
The replacement is an SVG sprite. Each icon is optimised and accessible by default.
The harder problem
When I joined there were four product teams using the design system. There are now nine, with fifteen to twenty expected by the end of the year.
The system is solid. The adoption isn’t always.
When the build doesn’t match the intent, that’s a front-end foundations gap. Components implemented incorrectly, CSS overridden with !important, markup that doesn’t follow the documented structure. That’s what you get when engineers are handed a framework before they’ve had time to learn what’s underneath it. It’s not unique to Royal London. The industry spent years prioritising full-stack generalists over front-end specialists, and most organisations are now living with the consequences.
A design system is supposed to speed delivery up. Without those foundations it slows teams down. Closing that gap takes time, money and backing from the top. We’re working on all three.
Accessibility shows the same thing. The design system components are built to standard, tested and signed off by the Accessibility Centre of Excellence. What fails in the product is the implementation: incorrect markup, missing attributes, overridden styles. The system can’t fix that on its own.
What’s different
The pipeline enforces consistency that manual maintenance couldn’t. Before it, typographic scale, spacing and colour values drifted between teams. Nobody was careless. There was just nothing to check against. Now when a decision changes in Figma, every product using the system gets it.
The system handles the boring eighty percent, so teams can spend their time on the twenty percent that’s actually theirs.
The grid and icon work are quieter wins. Less noisy markup, better accessibility defaults, a codebase that’s easier to read and reason about. They won’t show up in a dashboard. They show up when someone new can read the code without asking for help.
What’s still unfinished
The foundations gap. I knew it existed before I started. I underestimated how much it would shape everything else.
I’d rebuild the pipeline. We started with a spike that proved the concept and moved it into production, which was the right call at the time. It works. But it was built to solve the immediate problem rather than the permanent one. Given the chance, I’d keep everything it does now, add the Figma publish webhook, and design it to last instead of growing it out of a spike.
I’d also approach team engagement differently. We tried office hours. Attendance was low. Teams tend to get in touch once something has already gone wrong. What would work better is getting in earlier, closer to where the work happens. We haven’t worked out how yet.