Design systems don’t usually struggle because someone made a bad decision. They struggle because small teams move fast, requirements grow, and the capacity to revisit earlier solutions rarely keeps pace with the demand placed on them. What worked well for four teams looks different at nine. What works at nine will need revisiting at twenty.
That’s not a criticism. It’s the reality of building a system with a small team under delivery pressure. 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. There was a token layer. There was a grid. There were icons. The foundations existed and were holding up.
But the system had been built for where Royal London was, not where it was going.
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 drifted. Names diverged. The system said one thing; the product shipped another.
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, intentionality was hard to read, and every layout decision was expressed as a string of classes rather than a clear structural choice.
The icons were font-based. Fast to implement at the time. By the standards we now hold, accessibility, performance, flexibility, not good enough.
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. Not just updating the tokens, but building a process that meant they’d stay updated.
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 one named deliberately, each one traceable back 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 — not to slow things down, but to catch anything unintended before it ships. The goal is a Figma publish webhook that triggers the full pipeline automatically. We’re not there yet, but what we have is a significant step up from manual synchronisation.
A grid that says what it means
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. The intent is legible. The decision to move from flexbox to CSS Grid wasn’t just about aesthetics. Support levels had reached the point where the tradeoff no longer made sense, and the data-attribute approach gives us a cleaner, more intentional surface for expressing layout decisions without polluting the class list.
An icon system that actually works
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 properly structured, individually optimised, and accessible by default. A straightforward change that closes a meaningful gap.
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.
The gap between intent and implementation is a front-end foundations gap. Components implemented incorrectly, CSS overridden with !important, markup that doesn’t follow the documented structure. These are patterns that signal engineers working with frameworks they haven’t yet had the chance to build deep foundations underneath. 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.
The cost is real. A design system is supposed to accelerate delivery. Without the foundations to meet it, it creates friction instead. Closing that gap takes time, investment, and organisational will. We’re working on all three.
The accessibility picture reinforces this. The design system components are resilient, built to standard, tested, signed off by the Accessibility Centre of Excellence. What’s failing in the product isn’t the system. It’s the implementation. The same patterns that break accessibility are the same patterns that signal the foundations gap: 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 — not through carelessness, but because there was no single source of truth. Now when a decision changes in Figma, it propagates correctly across every product consuming the system. Consistency is a default, not a maintenance task.
Teams are building more confidently within the system. The 80/20 principle applies here. The system handles the eighty percent, freeing teams to focus on the twenty percent that’s genuinely product-specific. That’s the point of a design system. It’s not to make everything the same. It’s to make the common things easy so the specific things get the attention they deserve.
The grid and icon work are quieter wins. Less noisy markup, better accessibility defaults, a codebase that’s easier to read and reason about. These aren’t the kinds of changes that show up in a dashboard. They’re the kind that show up when someone new joins a team and can understand the code without asking for help.
Adoption has grown from four teams to nine since I joined, with more in the pipeline. The system is being used. That’s the measure that matters.
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 — the right call given the constraints at the time. It works. But it was built to solve the immediate problem rather than the permanent one. Given the chance, I’d rebuild it properly: keeping everything it does now, adding the Figma publish webhook, and building in the robustness that comes from designing something properly rather than evolving it forward.
I’d also approach team engagement differently. We tried office hours. Attendance was low. Teams tend to reach out when something has already gone wrong rather than before it does — that’s familiar, and it’s nobody’s fault. It’s the nature of delivery pressure. What works better is something more embedded: earlier in teams’ processes, closer to where the work actually happens. We haven’t found the right shape for that yet.
The technical work holds up. The token architecture is solid, the grid has evolved and is using native CSS Grid, and the icons are more accessible. What I’d change is the pipeline — rebuild it properly rather than evolve it — and the point at which we start talking to teams about what good implementation looks like. Earlier, and closer to the work. The system is built. Getting it used well is a harder problem, and a different one.