# Moving a product design team from Figma to code-first

Selzy, remote, email marketing platform, 2026, ongoing

I lead the move and built the AI setup the team works in: skills, rules, scripts and a layout template.

- Role: Product design lead
- 0 — new Figma mockups from our team since May
- 5× — faster on a big task, my estimate
- ~20% — of design time on building, was 50%
- 35+ — real tasks done in code since May
- 107 — iterations in Jira, anyone can take over
- 4 of 4 — designers on the team work in code

Tags: Email marketing SaaS, Remote, Team of 4 designers, Claude Code, Cursor, Codex

## My setup for the Selzy design team

Before, every prototype was set up its own way: 11 different sidebars, 5 ways to wire the UI kit. I built one template, the agent skills and the scripts. Now any designer starts a prototype on the real UI kit with one message. Replayed from a real session.

## A prototype has to match prod

Prototypes drifted from prod. Changes in prod don't always reach design, so the latest prototype stopped matching the product. Under a deadline, a PM and I made quick fixes in Figma, and the developer ended up with three versions: Figma, the prototype and prod.

After that, I made it a rule: a prototype has to match prod. This is the pricing page. Engineering asked us to bring its prototype in line with prod, so every fix now goes into both at the same time.

## Claude gives the average

Anyone can build a prototype with Claude now. Building got cheap. The decisions inside the prototype are still the designer's.

Claude answers with what it has seen most often. A library like Mobbin keeps strong and weak screens side by side, and without knowing which is which, Claude goes for the middle. With our product's limits on top, the middle drops below average.

## Localization stopped being a surprise

Translated text often runs longer than English. Before, we didn't see every language on every screen until release, so layouts broke and got fixed in prod.

Now the prototype shows every state in every language before handoff. Long strings get fixed in the prototype, not in prod.

Below is the plan chip from the Selzy topbar. It changes with the plan and with how much of its limits is used. Here it is in two states, the free plan and the warning at 90% of contacts, each in English, Portuguese and German, all from one prototype.

## Every step in Jira

An iteration used to be everything a designer did before the first review with the PM. Two of them took three and a half weeks. Now an iteration is one session of two or three hours, and each one ends in Jira with the prototype attached.

So every step of a task is in one place, and any designer can pick a task up at any step, without a long handoff.

## One phrase to close the loop

At the end of a session the designer says “let's wrap up for today.” The wrap-up skill reads the actual changes, writes the commit message and builds the iteration as one standalone HTML file.

Then it drafts a comment on the Jira task with the file attached right in it, and posts only after the designer's ok. Every iteration of a task stays in Jira as a working prototype the team can open.

## A small edge case from the cleanup

A developer and I discussed a small edge case during a design system cleanup.

Two spacing tokens, space-xs and space-s, had the same value, but different parts of the product used different names. For existing code, an adapter makes space-xs use the value of space-s, so everything still looks the same.

We're cleaning up in stages. The adapter buys time. But what if we later want space-xs to mean a smaller gap?

## Where we started

Selzy is an email marketing platform with more than 50,000 customers and more than a billion emails delivered every month. I lead a team of four designers: three product designers and a content designer. We work with six PMs, all remote.

When we started, it was the usual cycle: Figma files, handoff, fixes after release. Design and iterations were slow, and so was development.

The design system was old. Parts of the product live in separate repos and release on their own schedule.

In May I moved the team from Figma to prototypes in code, on the product's real UI kit. An AI tool can build a page from a prompt, but on generic components, and that shows little about our product. A prototype on the real kit shows real states, real text and every language before engineering starts.

The tool changed, not the job. We still decide how a screen should work. The difference is depth: instead of a set of screens, we build a working model of the product, with its logic, scenarios and every state.

## How the team moved

At first it was scary for everyone. It felt like we would stop being product designers. I tried not to push. I showed how I work on my own tasks, said when I didn't know something either, and we figured things out together. I helped along the way and steered gently. I also set up calls with designers from other products who had already brought AI into their teams.

Teaching happens on real tasks and at our weekly syncs. One designer came from email template design and had never opened a code project. By the end of June, the whole team was committing prototypes to one repo, each in their own way.

## The setup

Every task gets its own project in TypeScript, React and Vite. The real UI kit and icon library come from the frontend repos, locked to versions we've checked.

Any designer has to be able to start a project with one command, so I wrote one script that sets it all up: it clones five repos, switches them to those versions, generates 1,068 icon components from SVG and rebuilds the index. It's safe to run twice and never overwrites local changes. The test: someone else runs git clone, setup, npm install and npm run dev, and it works with no manual fixes.

Designers don't need the terminal for any of it. The agent runs the setup and prepares the commits. Every session starts by pulling the team's latest changes, so everyone works on the current template, skills and projects.

Before the template, I had the team audit the prototypes repo. They found:

- 25 project folders
- 19 separate Vite apps
- 11 different sidebars
- 5 ways to wire the UI kit
- 5 ways to build a standalone

So I built one layout template, with the sidebar, top bar and account menu rebuilt from the product's own components. The kickoff skill copies it for every new task. Copied, not generated, so every designer starts from the same file. The template has versions and a changelog, like a product, and every copy records the version it started from.

Rebuilding it from the code wasn't enough. About 30 small differences from prod slipped through. I wrote a script that measures the live product, and it caught all of them.

The template holds what rarely changes. Screens that change often go into a separate library of ready-made pieces, sorted by product area, each with the date it was last checked against prod. A designer takes a piece, checks it against prod and finishes it for the task.

I wrote the rules every agent follows, in one file, AGENTS.md. Nobody makes up interface text. It comes from the product's real translations in Crowdin, not from screenshots. Claude would rather read a screenshot than a repo, so the rules send it to the repos first. The agents are also connected to Jira, Figma and Mobbin.

Two skills are mandatory, and I wrote both. Kickoff finds the project by its Jira key, or starts a new one from the template. Wrap-up ends every session with a commit and a Jira comment. Both live in one folder any AI tool can read. We use Claude Code by default. Codex and Cursor have worked from the same files too.

## What an iteration looks like

An iteration used to mean everything done before the first review with the PM. Two of them took three and a half weeks. Now an iteration is one session of two or three hours.

Every iteration ends the same way: a single HTML file anyone can open, a commit, and a Jira comment on what changed and why, like in the thread above. So every step of a task is visible, the flow is the same for every task, and any designer can pick a task up at any step, without a long handoff. A designer can do three iterations in a day. We've made 107 so far, across more than 35 tasks.

Before a call, everyone downloads the latest iteration and clicks through it on their own machine, so on the call we discuss a working thing, not a picture. Feedback comes back through Jira and chat. The next session starts from the Jira task: the agent finds the project and reads its notes and history before it changes anything.

## Before handoff

Prototypes go to support and marketing first. Support clicks through them with the customer's questions in mind, and their notes come back as fixes before engineering sees the task.

## Handoff

Engineering gets the whole project, with links to the discussion, the UI kit and the repos. Before that, wrap-up strips out anything the task didn't ask for. The designer walks the developer through it with prod open in the next tab: this comes from here, that comes from there.

One PM brought a task with Figma mockups. We fixed them in Figma, and he still asked for a prototype at the end. It's easier to write the spec from it, and easier for engineers to read.

Portuguese and German text runs long, and layouts used to break after release and get fixed in prod. Now the team sees every language in every part of the interface before handoff, like the topbar states above. The content designer and the localization manager were the first to say so.

## The design system

A prototype on the real UI kit inherits all its problems. Moving to code gave us a strong reason to clean it up. It isn't simple. The product lives in 12 frontend repos that release separately, so a token can look unused in the kit and still be used by a live page somewhere else.

I split the cleanup between three designers and mentor them through it. One takes colors, one takes shadows, overlays and layers, one takes sizes. Each writes up what they find as an HTML page built with Claude, not a slide deck, and defends it on a weekly call with the frontend lead. I run those calls. The audit runs on scripts that collect every color, shadow and size from the kit and the product repos, so anyone can rerun it and get the same numbers.

We work in a fork of the UI kit, so the product doesn't change while we clean up.

I set the stages of the cleanup. First the names, then the duplicates. Old names stay as aliases until a script replaces them across all repos. Then the token layers: primitive, semantic, component, with new scales for shadows, layers, spacing and borders. Visual changes get a separate review, with before and after side by side. My rule is backwards compatibility first, cleanup second.

The last stage is moving the components to the new tokens. We try the new kit on one page of the product first, then roll it out next to the old one, piece by piece. That's where we are now.

## What changed

In Figma, half of the time went into building mockups by hand, and the other half into feedback and adjusting them after team syncs. It's hard to think through every state of a screen when half the time goes into drawing it. Now building takes about a fifth of the time. The rest goes to research, hypotheses, scenarios and states, and to product decisions with the team. We see flows, states and every language much sooner, catch mistakes earlier and ship fixes faster.

## What stays with the designer

Claude took over the building. The designers on the team now work more like design engineers: they give agents tasks, build and test hypotheses fast, and take the one that wins all the way.

What stays with the designer is what Claude can't pick for us: what the user actually needs, which pattern fits, how deep to go at this stage of the task, and whether the same problem is solved the same way across the product. That comes from knowing the audience and from years of looking at good and bad interfaces.

My part as the lead is the decisions. I build the process and the design system, set the direction and make the final call on the interface. That keeps the product consistent, however many hypotheses we run.

## What broke

Commenting got worse. In Figma, PMs and marketing could leave a comment on a pixel. Now they screenshot a prototype and paste it back into Figma to mark it up. We haven't solved this yet.

Prototypes drifted from prod. Changes in prod don't always reach design, so the latest prototype stopped matching the product. Under a deadline, a PM and I made quick fixes in Figma, and the developer ended up with three versions: Figma, the prototype and prod. After that, I made it a rule: a prototype has to match prod. A designer checks it against prod before starting a task, and Figma is only for text edits.

The agent made things up. In one prototype it found leftover JavaScript, decided it was a feature and built states nobody asked for. Engineering caught it in code review. Now, before handoff, wrap-up removes anything the task didn't ask for.

The first version of the kickoff skill built the setup from the repos for every task. It worked, but each designer's setup came out a little different. That's why the skill copies the template now.

## What's next

More ready-made pieces, starting with the rest of Contacts. Token rules written down so agents can follow them, and a lint check that flags raw values in code.

After the cleanup, prototypes will match the product more closely, and engineering will spend less time on each task. New ideas and changes will be easier too, because a working system is easier to change than legacy code.

Source: https://hochuzhrrat.com/selzy
