Case study · Fortinet
Designing the system, not the screens
Across our VP's scope, a small design team was supporting more products than it could realistically touch by hand: ten or more existing cloud products, plus roughly three new 0→1 products each year. The system started from that gap. We needed a way for designers and engineers to move faster without rebuilding the same foundations, re-solving the same patterns, or waiting on the same decisions every time a product needed to ship.
01A system is leverage, not consistency
There was no budget for a design system when I joined the team, and no one dedicated to maintaining one. Whatever we built had to come from time carved out around existing product work.
At first, the problem looked like consistency. Each product had grown around whichever third-party UI library its team had chosen at the time, so the same company ended up with different visual languages, interaction patterns, motion, and accessibility gaps across products. The bigger pain was the repeated work behind it. A small team kept rebuilding the same foundation and waiting on the same decisions to be made again.
So the system had to do more than make products look aligned. It had to give designers and engineers a shared starting point, reduce the amount of back-and-forth needed to ship basic UI, and make the common parts of product work easier to reuse.
Consistency mattered, but only because it gave the team leverage. If the system could handle the repeatable parts, the visual language, interaction patterns, motion, and accessibility, then the team could spend more time on the parts that actually shaped the product: what problem it solved, how the workflow behaved, and where users needed to go next.
02Design for the organization you have
The constraints were not background details. They changed what the system could be.
Even under one VP, the products were built by separate teams, in separate repos, with different component stacks and different habits. Some of the duplication lived in code. Some of it lived in old Sketch files. Some of it lived in how each team had learned to solve the same product problem on its own. The product surfaces also had little connection to Fortinet's marketing brand, so the system had to bridge product UI and brand direction instead of treating them as separate worlds. A Figma library alone would not have fixed that.
Scale made the problem sharper. Across our VP's scope, roughly three products launch from scratch in a typical year, on top of the ten or more we already had to support. With only a small design team, the system could not depend on designers reviewing every screen or engineers asking us where every button, form, and page pattern should go. It had to help non-designers make reasonable decisions when we were not in the room.
The environment also ruled out the usual design-system playbook. Because this was cybersecurity, no external vendor tools were allowed near internal product work. No Storybook, no ZeroHeight, no analytics platform we could simply plug in. If we needed a source of truth, a component playground, or a way to check whether teams were using the system correctly, we had to build it ourselves.
So the system had to stay close to code, light enough to adopt, and useful without a dedicated team behind it.
03Fewer decisions, not more components
I started where most design systems start: auditing live products, stripping out legacy noise, and rebuilding from the smallest reusable parts up to a core set of components. Buttons, inputs, tables, modals, navigation, the obvious things. That work mattered, but it was not where most of the time was being lost.
The more I sat with engineers, the clearer it became that the slow part was rarely dropping in a component. It was everything around it: how to lay out a settings page, how to structure a form, how to compose a dashboard, what belongs in a wizard versus a table, and where actions should live. Those were design decisions, but they were being made over and over by people who did not really want to be designing.
That was when the system shifted from components to patterns. I started pulling common page types, flows, and recurring product patterns into near-finished guideline pages instead of treating the library as a pile of parts. The goal was to let someone start from a working pattern, swap in their own content, and still end up with something coherent.
I could tell it was working when engineers started answering their own questions with it. Someone building an onboarding stepper, unsure where cancel, back, and next actions should go, could pull up the onboarding pattern and follow it instead of guessing or asking me. That was when I knew the system was doing more than adding components. It was taking small design decisions off the team's plate.
04A system should outgrow its creators
With no dedicated team, maintenance could not be something we solved later. If every screen still needed design review, then we had not really built a sustainable system.
A three-level, multi-theme headless design system. Color, type, spacing, elevation, and motion all moved into a three-level token structure that could theme across Fortinet's product areas. That structure mattered most during the company-wide brand renewal. Because the system already keyed visual decisions off tokens, we could absorb the new brand, support four product themes, and add light and dark mode without redesigning each product surface by hand.
Reusable foundations. The base library grew into 50+ Figma and React components with usage guidelines and interaction patterns. Even before the later AI work, those components cut front-end implementation time by roughly 40% and made day-to-day product work simpler.
Boilerplates for B2B products. The component library solved the parts. It did not solve the pages. So we also built boilerplates for the product surfaces teams kept rebuilding: forms, dashboards, license pages, configuration flows, and other common B2B patterns. Instead of starting from a blank page, engineers could start from a real B2B page shape, with components and patterns already laid out for the use case. They could keep the layout and interaction pattern, then swap in product-specific content.
Design and code in the same place. Since external tools were off-limits, we built our own component playground to keep the Figma and React sides of the system aligned. The playground became the shared surface for the system: components, specs, boilerplates, patterns, changelog, contribution notes, and live theme switching. Teams could install the package and start from a themed, on-brand setup instead of wiring everything together piece by piece.
Accessibility as a system behavior. I did not want accessibility to depend on whether the person building a component happened to know the right contrast ratios, focus behavior, or screen-reader semantics. I tried to move the easy-to-miss parts into the system itself. Color pairings were constrained at the token layer, and components were backed by axe and Playwright checks for keyboard behavior, focus management, and semantics. If a component fails its own accessibility tests, it does not ship.
Maintenance that did not live in my head. I wrote AI agent skills for the repetitive parts of system work: checking token naming changes, reviewing component API variants, generating changesets, syncing with Figma design files, and guiding new designers and engineers toward correct system usage. The design team still reviewed anything that changed a public API, but the routine checks no longer depended on someone remembering every rule.
Contribution without gatekeeping. Over time, the system became less dependent on its original builders. I wrote a contribution skill that helps teams check their own work before asking for review: whether a new token follows the naming system, whether a component API or prop overlaps with existing components, what should be designed as a subcomponent versus controlled through props, and whether the proposed variant has a clear enough use case to belong in the system. It gave contributors a way to check their work against the same standards I would use, and contribute back without waiting for me or a dedicated design-system team to step in.
05Every abstraction has a price
I did not get the scope right at first. My instinct was to give every design element its own tokens, so the system could absorb almost any future theme change. It felt safer to make everything configurable.
That turned out to be the wrong kind of flexibility. At one point, the system had grown to almost 20,000 tokens across 50+ components. The naming convention was not straightforward enough for people to reason through, and even linting or automation could not reliably predict the token someone meant to use. Instead of making the system easier to maintain, the extra abstraction made it heavier, harder to search, and harder to trust.
It took a few rounds of cleanup to bring it back down. That cleanup changed how I think about abstraction. Abstraction only helps when it protects against a real kind of change. Past that point, it just becomes more system to maintain.
06Fit the company, not the ideal
Not every designer gets to work in a culture where design is already valued and the tooling is set to industry standard. The work was not about building the ideal design system I had in my head. It was about building one that fit the company I was actually in: its constraints, its habits, and the way people already made decisions.
You cannot change that overnight. So part of the craft was knowing when to push, and when to make the better path easier to follow. Instead of a heavy contribution process, I kept the system open: if someone hit a token that fell short or a pattern that was missing, they could propose a change. The standards stayed clear, but the gate stayed light.
With no dedicated team to maintain the system, it could only keep growing if other people felt like they had a hand in it. My job was not to control every answer. It was to keep the direction clear enough that other teams could make good contributions without asking for permission every time.