Let's talk
← All posts

2026-10-05 · 3 min read

Design systems that people actually use

How a private npm package, a Markdown docs site and a lot of sprint planning made a shared component library the single source of truth for up to 10 teams.

On this page

A design system succeeds when teams reach for it without being told to. Up to 10 teams used the one I helped build, and almost everybody adopted it. Building the components was the easy part. Getting them into everyone's hands was the real work.

The problem: every team had its own UI

Teams across the company managed their own code independently. That is good for speed, but the interface drifted. As you moved from one product to the next, even though you reached all of them through the same platform, tables, layouts and menus looked and behaved differently.

One source of truth

We built a shared library that every team picks its components from instead of building their own. It covers what a frontend application needs, from data-heavy tables and dashboard layouts to the sidebar, filters and dropdowns. Colours, spacing and type are defined once as design tokens, so a change happens in one place and reaches every product that uses the library.

Docs that feel like writing a README

We documented the library on a site built with Nextra, a documentation framework on top of Next.js where every page is a Markdown file. It was a straightforward choice for us at the time because of its MDX support: writing a docs page is as light as writing a README, which matters, because documentation that is painful to write does not get written.

Hosting it privately was harder than building it

The library lives in a private registry on Azure. Setting that up was harder than I expected, but we got there. Azure recommends two .npmrc files. The one in the project says where to find the package, and it is safe to commit:

# .npmrc in the project (example)
@your-scope:registry=https://pkgs.dev.azure.com/<organisation>/_packaging/<feed>/npm/registry/

The credentials go in a second .npmrc in your home folder, never in the project.

The first install is where adoption can die

To install the library, every engineer had to create a personal access token in Azure and put it in that user-level .npmrc on their own machine. It was the only way to install the package. It is the right call for security, because the token never lands in the repository, but it is also the very first thing a new user hits.

The pipeline needs its own way in

A personal token cannot be used in a build pipeline, so the build needs a token of its own. Our DevOps team handled passing one into the build. Getting the library to install in each project's CI pipeline was a second hurdle, and we sorted it out.

Adoption is a planning problem as much as a technical one

Every team has its own roadmap and sprint dates. Some adopted the library early. Others could not until later, and for a while the interfaces still differed. What worked was collaborating with the product teams to put the migration into their sprints, so engineers had the time to do it. In the end, up to 10 teams used the library, and almost everybody adopted it. One result I could measure: page build time dropped by about 25%.

If I were starting again

  • Make the first install painless: a clear guide for the token, ideally a script.
  • Solve CI access on day one, not after the first team asks.
  • Keep the docs as easy to write as a README.
  • Put adoption on each team's sprint, with the product team's agreement.
  • Measure something, so you can show it worked.

Working on something similar?

I'm open to contracts, consulting and collaborations.

Get in touch →