ENPT
Back to Index

Teaching two design systems to talk to each other using Claude

May 12, 20265 min readai, design, claude

How I orchestrated AI agents to cut a 36-hour weekly workflow down to 1 hour

Since joining Wave, I've faced several genuinely interesting challenges. Beyond adapting to a new industry (I moved from fintech to telecom), there was also a new way of working to learn.

On the projects for the client I work with, preparing handoffs in Figma meant taking every interface component and manually translating it into the language of our internal library, where each smallest interface element is a 'block' with its own specific properties and attributes.

How a component gets 'broken down' into blocks.
How a component gets 'broken down' into blocks.

So the process looked like this:

Manual, repetitive work, but necessary to keep development flowing smoothly. Still, I was spending around 36 hours a week on this process. There was barely room left for anything else in the week.

That’s when I started thinking about how to optimize the process to save time.

Why "automate" wasn’t the right word

My first instinct was to put together documentation directly in Figma and ask the devs for help writing a script that could automate the matching between Figma components and blocks.

The problem is that the two systems run on different logic. In the client's design system, a component is one complete unit. In our library, that same component might break down into several blocks, or simply have no equivalent at all. A direct match isn't possible.

A script follows rules, but what I actually needed was something that could interpret context.

From that realization, I started exploring agent orchestration using Claude. Not because I already understood the concept deeply, but because I understood that the problem called for a solution that could 'reason', rather than just execute a chain of rules.

How the agents "learn" to translate

The agent orchestration process.
The agent orchestration process.

The core logic is simple to understand: the orchestrator reads our entire block library, with all its properties, variants, and rules. Then it reads the client's component. Instead of trying to make a direct one-to-one match, it breaks the client's component down to the smallest possible unit and tries to rebuild it using the blocks' vocabulary.

It works like a translator that understands grammar, not like a dictionary that just explains what each word means.

The result is a representation of the full structure: the parent component and all the child blocks inside it, with the correct properties, in whichever format I choose — documentation directly in Figma, or a ready-made JSON, in the format the devs need for implementation.

When a block or property doesn't exist in our library, the agent doesn't ignore it; it flags it and logs it in a spreadsheet. That became part of the process, and eventually we'll have a list of gaps to evaluate and decide whether it's worth creating new blocks in our library or thinking of another approach.

Four problems solved at once

When I started mapping out what I needed to solve, I realized it wasn't one problem. It was four:

The whole process, from reading the API to the final documentation, happens directly in Figma, using a plugin I also built with Claude.

Block documentation in Figma
Block documentation in Figma

36 hours back

What used to take up nearly my entire week now happens in 1 hour, sometimes less. After generating all the documentation, I review the agents' output, adjust anything that wasn't found in the API, and that's it. This changed not just how I work, but also gave me time to focus on other tasks and keep up the quality of what I deliver.

Of course the agents make mistakes. Not often, but especially on heavily customized components, where the gap between the two languages is too wide for a clean interpretation.

The most frequent case is a component that uses Figma's auto layout: when the spacing between elements is set to 'auto', for instance, the agent interprets auto as zero, and the blocks end up glued together when the JSON is rendered. It's a small error, but it shows up regularly enough to stay on the radar, and for now it still needs to be corrected manually.

Human review is still part of the process, and I think it probably always will be. The goal was never to eliminate our team's review, but to optimize, and maybe eliminate, the mechanical and repetitive work that used to eat up so much time every sprint.

Process design is design too ✨

The whole orchestration was built with Claude. What I learned is key to making any of this work is thinking the problem through carefully before picking the tool. First, define the comparison rules, the expected output structure, the edge cases. The AI did the heavy lifting, but the process design was 100% human.

Originally published on Medium

Let's connect! :)