Designing the harness

How I cross-skilled into the front end, then built it into how a whole agency designs, while the tools changed under me.

Role Design Lead · Design Engineer
Client Internal, then a retailer and a B2B software company as the first engagements
Team Me on design, the design kit and the handoff; the engineering team on the spec-to-code compiler
Timeline 2013–2026
Status Ongoing; the tools keep changing
Result The engineering compiler builds from design’s handoff, not from Figma
Tags design-systems · agentic-ai · design-engineering · process

Key learning

I know the output; there are a hundred ways to get there. The tools changed every few months. What held was the output: design written down as a specification complete enough to build from, and to check against.

Overview

For years, design showed clients pictures of a thing, and then it didn’t look like that when it was delivered. The little things got deprioritised one at a time, because no single one mattered as much as an integration. At the end of a project they piled up and looked like new scope, when they’d been part of done all along. Death by a thousand cuts.

Design QA was supposed to catch it: reach out to the designer before code review. It was manual, not ideal, but necessary, and it was always seen as expensive. The wrong people ended up holding the final look and feel. That was always design’s job, but the tools limited what design could do and when.

This is the record of how that changed, first for me and then for the agency I was at: from Figma as the source of truth, to a design kit in code where a component, a page or a brand is written down once as a specification and everything else is generated from it.

The constraint

Every tool I built got replaced, sometimes within weeks. The direction didn’t change, but nothing I started with survived to the end.

  1. The design file was the source of truth, and it drifted. A design source sat pinned three and a half months stale while every check passed.
  2. The same components were built more than once. One sales prototype re-authored thousands of lines of components that already existed.
  3. Standards lived in documents. A standard applied by hand is not a standard.
  4. Teams and clients were trained on Figma-first. One developer built from Figma for a month after the code had become the source.
  5. New tools went in before the process changed around them.

Approach

Cross-skilling myself first

Product design is a spectrum. I’ve never been the research guy; my side of it is the front end, the presentation layer.

For years I wasn’t seeing the thing I designed get built the way I wanted. I was skipping the why. I was giving developers the final thing and not the process behind it, and some projects didn’t go great. What I noticed was that when I got in there and got my hands on it, I could express it, even when I couldn’t say why. Developers who were patient with me taught me the way to work with code. Every headline at the time was “should designers code?” I ignored most of that and leaned in, because I wanted to do it anyway.

The first thing I shared was a talk to the design community of practice, and a toolkit for designers who were curious. By no means do designers have to code. I’m only one type of designer, and it’s a spectrum. The line from that toolkit that held through every tool after it: the trick is making sure the core of what we are doing is interoperable, agnostic of toolchain.

A year later the talk was about moving detailed design and design QA into code, with Figma kept for mockups and flow. I couldn’t sleep at night knowing it wouldn’t look like that in code. Four months after that, Figma was no longer the source of truth, but a scratchpad for ideation. Then the setup guide turned into a process: designers code, developers integrate, and the ownership is written down.

Making the playbook run

Before Genie, there was a discovery playbook. Nobody ran it, so the second time it had to run.

Genie started in the spring of 2025 as a personal experiment and got out of hand: an agent in Slack that read a project’s context and did the repetitive work of discovery. The part that lasted was the audit, which grew into a pipeline: audit, compare, synthesise, map, prototype. The full story is here.

Putting design where the code is

The second tool was a Storybook workspace per client, one command to start, so designers could work in real components instead of pictures of them. The /design agent proved the idea and showed its limit: a workspace per client still meant a copy per client.

The third was the design kit. Tokens, components and page templates in plain HTML and CSS, the rules they follow, and the checks that enforce them, in one source every engagement starts from. It began in March 2026 as a documentation site and a Storybook, went through Tailwind and component-library experiments that I dropped, and settled on framework-agnostic HTML in May. Each client gets a branch and a brand on top of it, so a brand change is a diff, not a redesign. One client’s brand came to 58 lines, and it restyled every component.

Because the design kit exists, I don’t have to hold that complexity anymore. I can focus on what matters: what it does, what it communicates, and how it delivers the goal of the user and the client.

The first engagement, end to end

The first time the pipeline ran on client work from start to finish was a website replatform for a B2B software company. Tokens were extracted from the live site instead of redrawn. Code and Storybook were the source of truth, and Figma became a wireframe layer. The audit covered 348 components, 84% of them already in the kit. The handoff was 119 components with spec contracts and 54 pages.

It was also where the new way of working showed its costs. In a coded prototype every spacing note is a commit, so review looked like breakage when it wasn’t. Feedback lived outside the tracker until it was suddenly 166 items. And I’d claimed to know the solution, not just what would get done but exactly how, which got me in trouble. I’d never again go into a project ambiguous about the end result.

A standard applied by hand

A farm and home retailer came next. A colleague built the sales prototype for requirements, with every flow and integration in place, and I restyled it by hand. Two or three hours went into getting the hero banner to look how it should, not better than it could. The prototype carried 6,939 lines of Tailwind duplicating components that already existed, and about 1,550 of them were worth keeping.

The sales prototype built for requirements: a white header, a green category bar and flat colour blocks for the hero and promotion tiles Before: the sales prototype built for requirements, with every flow and integration in place. The retailer’s name and logo are replaced here.

The same prototype a day later with the design kit applied: the retailer’s blue header, a red promotion banner and a full-width photographic hero After: the same prototype a day later, with the design kit applied in the retailer’s own brand.

The colleague who built it said he couldn’t recognise his own prototype, and many people have since said the design added to it is what won the deal; the start moved up from December to October. That restyling should have been there by default. I need to take things to a hundred, not bring them up from minus ten. Sales now has a demo skill with the design rules built in, so a prototype starts at baseline, and the retailer’s work lives in a repo of its own, with Jira as the source of truth and Storybook as the deliverable.

What a spec is

A spec is the one file that says what a thing is, completely enough that it can be built from it, in any framework, and checked against it. The test is to delete everything that was generated and rebuild from the specs.

The thing I got wrong, and it’s the common one: I assumed a spec was a token, then that it was a semantic token. It’s neither. A token is a word. A spec is a thing built from words.

id: COMP-button
component: Button
states: [loading, ready]
props:
  - name: variant
    type: enum
    values: [primary, secondary,
      tertiary, danger, inverse,
      secondary-inverse]
    default: primary
  - name: size
    values: [sm, md, lg]
    default: md
  - name: disabled
    type: boolean
class_rules:
  - always: “btn--{variant}”
  - when: “loading”
    add: “btn--loading”
render:
  - when: “href && !disabled”
    element: a
  - otherwise: true
    element: button
consumer_class:
  forwarded: true
  reason: >
    ~29 call sites use a hook
    class for parent layout;
    dropping it re-breaks them

Part of the design kit’s button spec. What you can set, the rules that pick a class, what it renders as, and the reason a rule exists, in one file a machine can read.

It’s not a generative accelerator if it isn’t generating from the spec. Building everything ahead of a project only means not doing it by hand. Regeneration doesn’t mean starting from scratch every time. It means a new component or a new prop isn’t a big deal.

Checks that report success

The hardest failures weren’t breakages. A passing check is not a rendering. A conformance check reported zero unknown classes on a codebase it had never read, and a stale design source passed every gate for months. The recurring failure is tools reporting success over ground nobody covered.

Deciding who decides

I decide what design is. Developers decide what dev is. We both decide how they talk to each other. A developer touching design is reviewed by a designer, a designer touching front-end components is reviewed by a developer, and neither role is removed.

A design-affecting change

Anything a customer will see goes to one of three lanes.

A developer touching design
is reviewed by a designer
A designer touching front-end components
is reviewed by a developer
  1. Lane 1 · Developer proceeds

    An existing component, variant or token

    Content and copy too, or a state the component’s doc already covers. A designer reviews the pull request.

  2. Lane 2 · Design owns

    Anything new and core

    A new component, variant or token, or a shared one like the nav or footer. A developer implements and reviews.

  3. Lane 3 · Stop

    A gap in the kit

    The design needs a state, token or slot the kit doesn’t have. It’s fixed in the kit first, never worked around with a wrapper or local CSS.

Three lanes for a design-affecting change. Neither role is removed; both gain a judgment seat.

Teaching it while it changed

I ran a workshop on the accelerator, took a design slot at the company town hall, co-led the craft workgroup at an internal AI summit, and wrote the docs for colleagues and for clients, the client ones without naming a single tool. The ask at the town hall was one line: when you open a pull request a customer will see, tag design. The rules and the guard now install as a plugin with one command, and it announces its releases in Slack.

Outcome

Most of the change is now process rather than a tool:

  • Client work lives on its own branch; fixes found on one client flow back into the shared kit, so the next client starts with them.
  • Design checks run on every pull request, and design publishes automatically.
  • The engineering team’s compiler builds from design’s handoff, not a stale Figma export. Five people have opened pull requests moving it onto a new design release.
  • Requests from developers come back the same day: across eight requested changes, the median from pull request opened to merged was about an hour.
  • Figma is an output on request, never the input. One Storybook is the review surface.
  • A client’s brand is scraped from their live site, and one command starts a new client: branch, handoff and deploy.
  • The plugin replaced Genie.

The design source holds 135 components and runs 35 checks. Correctness has a floor now. Quality doesn’t, yet: stories are still written by hand, 0 of 117 generated from specs.

What I learned

Every version I built was right for what I knew at the time and wrong a few months later, and what read as unstable was learning. I needed to soften my relationship to tools and processes. Not every designer is ready or able to work this way, and they shouldn’t have to; the job is to capture the complexity so people follow a good process without having to remember it. (The answer is always yes is the longer version.)

I don’t know the perfect way to deliver handoff, and I know it will change. I don’t know the future of design, but I know what it’s not.