Every designer knows the moment. You deliver a design you are proud of, and what comes back a few weeks later almost looks like it. The gap between two panels is four pixels wider, the typeface has a different weight, the loading screen you had thought of is not there. Nobody did anything wrong. The design was just rebuilt by someone who was not in the room when it was made.
That gap has less to do with tooling than with the assumption that design stops where building starts. In practice most design decisions are made during the build: what happens when a list is empty, when a name is too long, when the connection drops, when someone has no permissions. If that is not in the design, the developer decides it. Often well, sometimes not, and you only hear about it once it is live.
What we put in the design
So we design those states in. Empty, loading, error, too much, no permissions. It is the least glamorous part of the work and the part a handover actually breaks on. Next to that we write down why something is the way it is, in a few sentences beside the screen, so a later change does not undo the reasoning by accident.
And we do not send it over. We walk through it, with the developers in the room, and after that we stay close. With a team we onboarded this week, we now join their weekly refinement. A question about a hover color then costs two minutes instead of a three-day email thread.
One set of agreements for color, space and type
The biggest difference is made by something you never see in the finished product. Every color, every unit of white space, every font size and every corner radius in the design has a name. The color of body text is called "text, primary". The space between two fields is called "medium". No six-character codes, no loose pixel values. If the code uses those same names, the design and the product are the same thing in two forms. Change the primary text color and it changes in Figma and in the product at once, and nothing drifts.
It also means we tell developers what not to copy. Figma can spit out code for any screen, and that code is not usable: fixed widths in pixels that do not scale, colors as bare numbers. We say: read the sizes and the names off it, and build it by hand on the agreements. That is slower on day one and faster on every day after.
Why we increasingly build it ourselves
Long before AI came into it, we already sat next to the developer. What has changed is that we now often do the building ourselves. With AI coding tools we can take a validated design all the way to working software, with the same agreements for color and space as in the design, and with accessibility built in from the start.
It starts earlier than that. We now build a prototype in code, instead of in clickable screens. Buttons work, fields take real input. It feels like the product because it essentially is the product. The choices that used to surface during the build, like what happens when the field stays empty, we now make in the design phase, because we run into them. What the client approves is what goes live.
We are open about the fact that AI does the heavy lifting on the code there. Our craft is design. We do the steering and the choosing, and we keep the result true to what was designed. And if a project needs engineering that goes deeper than we reach, we say so and bring in the right people.
Clear documentation of design decisions for smoother handoff and better collaboration with developers.