Design System: Governance and Adoption

Published: (December 9, 2025 at 07:02 AM EST)
6 min read
Source: Dev.to

Source: Dev.to

Introduction

Building a design system is only half of the work.

Yes, it’s challenging to evaluate multiple options, gather feedback from stakeholders, and implement everything in code – but this is still the part most engineers feel comfortable with. We know how to explore technologies, analyze requirements, write specifications, and eventually ship the technical foundation.

The real challenge, at least for me, was bringing this new solution into the daily life of other developers. Any new system introduces friction: it requires time, attention, and a willingness to go through the learning curve. And when teams are under roadmap pressure, people naturally gravitate toward the approaches they already know – even if those approaches caused the very problems we were trying to solve.

On top of that, some decisions that seem perfectly reasonable at the beginning may turn out to be inaccurate or incomplete – not only when they meet real‑world usage across multiple teams, but also as that real world evolves faster than expected.

That’s what I want to share in this final part of the series: how we handled governance, adoption, and the human side of making a design system truly work.

Why adoption is hard (even when the tech is good)

Common challenges familiar to any company

Adoption is rarely a technical problem – it’s a human one.

Even when the new system is objectively better, teams face familiar obstacles:

  • People prefer familiar tools, especially under roadmap pressure.
  • New patterns require time, attention, and a mental shift.
  • Legacy code feels safe, even if it’s the cause of recurring issues.
  • Every team has slightly different habits, priorities, and constraints.
  • Benefits of a design system are long‑term, while costs are immediate.

In other words: even good technology doesn’t adopt itself.

What was hard in our case

Our situation wasn’t radically different from the typical one, but a few challenges stood out.

  1. Design‑side complexity – Since our single source of truth was Figma, understanding the correct meaning and usage of components – like when to use a Menu, a Select, or a Popover – isn’t always obvious if you haven’t worked deeply with accessibility‑driven patterns. Things get even more complicated when a design blends attributes of multiple components, such as a popup that allows switching accounts and shows contextual actions at the same time.

  2. Learning‑curve overload – The design system was built in parallel with a broader transformation of our frontend architecture: new monorepo structure, the first ui-kit package, migration from styled-components to PostCSS modules, introduction of Radix Primitives, design tokens, component architecture patterns, Storybook documentation, and Chromatic visual tests. Each change was reasonable on its own, but together they made adoption more demanding than it would have been with fewer moving parts.

Migration strategy: slow, controlled, predictable

Main principles for gradual and consistent migration

The foundation of our migration strategy was simple: move forward without breaking what already works. A full “big bang” rewrite may look tempting from an engineering perspective, but it is rarely justified for the business unless the gains are dramatic – such as a major performance improvement or a critical SEO uplift. Neither was the case for us, so gradual adoption became the most reasonable and sustainable option.

Our main principles were:

  • All new features must use the new components
    This applied both to Figma (as the single source of truth) and to code. New work should build on the new system; legacy components should remain only where they already exist. This ensures natural growth of the new system without forcing teams into expensive rewrites.

  • “If you touch it – improve it”
    This company‑wide rule proved extremely useful. Whenever someone modifies or refactors a piece of UI, it’s a good opportunity to migrate that part to the new components as well. Since the PR must already be reviewed and visually tested, merging the migration into the same change often reduces the total cost compared to doing it later as a separate task.

Together, these principles created a predictable and manageable adoption flow: slow enough not to disrupt product work, but steady enough to avoid stagnation.

Design review as part of adoption

In most teams, new designs are reviewed by a Head of Design or CPO before they are marked as Ready for Dev. However, neither of those roles initially owned the full context of the newly introduced design system – its components, constraints, patterns, or how they translated into code.

To bridge this gap, we introduced an additional review step for the first few months: Design System Review. This review was handled by two people who fully understood the system’s architecture and principles:

  • the Design System Lead from the design side, and
  • the Project Lead from engineering.

Benefits of this checkpoint

  • Catching inconsistencies early – Issues in component choice, naming, and patterns were flagged before any code was written.
  • Knowledge sharing – Designers learned how to use the new system correctly – which components to pick, how semantic tokens worked, when to use specific patterns, etc.
  • Better predictability – Designs handed to developers were more consistent, realistic, and aligned with the actual capabilities of the system.

This short‑lived review phase significantly accelerated adoption by ensuring that both design and engineering moved forward with the same mental model.

Developer Experience improvements

People naturally gravitate toward familiar behavior, so we introduced several DX‑focused guardrails to promote consistent usage of the design system and reduce friction:

  • Custom ESLint rules – Enforced correct usage of components and tokens (as mentioned in Part II). They provided immediate feedback in the editor, long before a PR review.
  • Marking all legacy components as deprecated – Even components not yet fully reimplemented were flagged. This wasn’t meant as pressure – just a clear visual signal that this is the old path.
  • Documentation (as a last resort) – Proper docs were written and maintained, but realistically, documentation works best as a safety net, not as the primary adoption tool.
  • Automation scripts – Tools to export Figma variables into code, generate boilerplate for new components, and streamline contributions to the design system.
  • A dedicated Slack channel – Centralised communication helped teams ask questions, share examples, and stay aligned. Most importantly, it created a sense of community rather than another rule to follow.

Together, these DX additions lowered the cognitive load of using the system and made the correct path the easiest one. Improving DX ensured that adoption didn’t rely on discipline alone – the system itself guided developers toward the right patterns.

AI: migrating in 2025 and beyond

As LLMs have become more accurate and context‑aware, a significant part of manual migration work can now be delegated to them.

We embraced Cursor and GitHub Copilot as migration assistants:

  • Automated migration guides – With a simple Cursor prompt, we generated structured guides showing how legacy component configurations should be adjusted to match the new API. These guides could also be reused directly as transformation prompts, e.g.:

    “Migrate all legacy Button components to the new Button from ui-kit using docs/migration-guides/Button.mdx.”

  • AI rules aligned with the design system – (content truncated)

Back to Blog

Related posts

Read more »