— The work behind the work
Royal London Design System
Token architecture, a design-to-code pipeline, and the harder problem of adoption at scale.
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 there was headroom.
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 this was a crisis. But none of it was where it needed to be.
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 system runs on three layers. Primitives at the base, the raw values, colour, spacing, and typography. Semantic tokens above that, mapping intent to primitive values. Around 600 variables across both layers combined. Component-level tokens at the top, scoped to specific patterns, adding a further 400. 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, a new package is published. Developer review is deliberately kept in the loop, not to create friction, but to ensure nothing unintended slips through. The ideal end state is a fully automated trigger on publish. We’re not there yet. What we have works, and it’s a significant step up from manual.
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, which screen readers handle 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.
What we’re seeing across teams is a familiar pattern: components implemented incorrectly, CSS overridden with !important, markup that doesn’t follow the documented structure. The system works when it’s used as intended. The gap between intent and implementation is a skills gap, engineers without deep front-end foundations implementing patterns they don’t fully understand.
This isn’t a new observation. The skills gap was visible on day one and it’s still visible now. I’ve been raising it consistently throughout my time at Royal London, and progress has been slower than I’d like.
The cost is real. Teams move slower than they should. Implementations need rework. Engineers who could be focused on product are instead untangling problems that a stronger front-end foundation would have prevented. A design system is supposed to accelerate delivery. A skills gap creates friction instead, and that friction has a business cost.
It’s not unique to Royal London. The industry spent years prioritising full-stack generalists over front-end specialists, and most organisations are now navigating the consequences of that in one form or another. The awareness is there. Closing the 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 a skills gap: incorrect markup, missing attributes, overridden styles. The system can’t fix that on its own.
What’s different
Brand consistency across products is measurably better. Before the token pipeline, typographic scale and spacing drifted between teams, not through carelessness, but because there was no single source of truth enforcing consistency. Colour values were maintained manually, which meant there was always a risk of divergence. Now the pipeline guarantees it. When a design decision changes in Figma, it propagates correctly across every product consuming the system. Typography, spacing, and colour are consistent by default, not by effort.
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 fifteen to twenty in scope for this year. The system is being used. The work is landing.
What I’d do differently
The skills gap. I knew it existed before I started. I underestimated how much it would shape everything else.
The pipeline is something I’d revisit given the opportunity. We started with a spike that proved the concept and moved it into production, which was the right call at the time given the constraints. It works. But it was built to solve an immediate problem, not designed for long-term resilience. Given the chance, I’d rebuild it properly, retaining everything it does now, adding the Figma publish listener we identified as the ideal end state, and building in the robustness that comes from designing something rather than evolving it.
The wider engagement model is something I’d approach differently too. 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 a pattern I recognise, and I don’t think it’s anyone’s fault. It’s the nature of delivery pressure. What I’d want is something more embedded, closer to where teams are working, earlier in their process. We haven’t found the right model yet. Finding it is still on the list.
The technical work holds up. The token architecture is solid, the grid is better than what it replaced, and the icons are where they should be. What I’d change is the pipeline completeness, the enablement strategy, and how early we start the conversation with teams about what good implementation actually looks like. The system can only do so much. The rest is people, process, and time.