The demo version of AI-assisted interface work is one prompt and a finished screen. The working version is a loop, and the loop is short on purpose: describe a piece of the screen, let the assistant build it against a real API, let the type checker be the first reviewer, read what came back, commit when it is green, repeat. None of the individual steps are clever. What makes the difference is that each one is cheap enough to run again, which is what keeps a wrong turn from costing an afternoon.
Set the context before you write the prompt
The first thing to get in place is the assistant's ability to ask questions about your library instead of recalling one. That is a single configuration entry pointing at mcp.orvain.dev, and it is worth doing before the first prompt rather than after the first wrong import, because an assistant that can query the real props stops producing the failure mode you would otherwise spend the session correcting.
The second thing is the local context: the file the code will live in, the two or three neighbouring files that show how this codebase does things, and whatever house rules are not obvious from the code. Assistants are good at matching a pattern they can see and poor at inferring one they cannot.
Describe the screen, not the markup
A prompt that specifies markup is a prompt that has done the hard part badly. The useful prompt describes intent and constraint: what this screen is for, what data it renders and in what shape, what it shows while that data is loading, what it shows when there is none, and what it shows when the request failed. Those three states are where generated interfaces are thin, and they are thin because nobody asked for them.
Name the structural constraints explicitly as well. Whether this is a server component, which part of it is allowed to be interactive, which breakpoints matter, and whether anything here is forbidden from reaching for browser-only APIs. Those decisions are cheap to state and expensive to retrofit.
Give it the data as well, in the shape the code will actually receive. A screen built against an imagined response has to be rewritten the first time it meets the real endpoint, and the type describing that payload is usually already sitting in the repository waiting to be pointed at. The same goes for the strings: placeholder copy written to fill a layout has a habit of surviving review, and occasionally of surviving into production.
Let the type checker review first
Strict types turn a plausible-looking generation into a compile error, which is the ideal outcome: a mistake that is found mechanically and described precisely. Run the type check as the first pass on anything generated, feed the errors straight back, and let the assistant fix its own output. This is the cheapest review in the loop and the one most often skipped in favour of reading the code, which is slower and worse at the specific job of noticing that a prop does not exist.
Keeping the generated diff small matters more than it sounds. A compile error in a thirty-line component points at its own cause; the same error in a four-hundred-line generation points somewhere in a haystack, and the assistant will happily rewrite the wrong part of it.
What still needs a person
Once the API is verified and the types pass, everything left is judgment. Whether the visual hierarchy matches the actual importance of the information. Whether the empty state tells someone what to do next or merely states that there is nothing. Whether the copy claims more than the product does. Whether the keyboard path through the screen makes sense in the order the elements appear. Whether this screen should exist.
Those are not gaps waiting for a better model. They are the parts of the work that require knowing what the product is for, and the reason the loop is worth running is that it clears everything else out of the way so there is attention left for them.
Keep the loop short
Generate one block at a time and commit at every green state. A long generation is hard to review, hard to bisect when something is wrong two days later, and hard to attribute when it works for reasons nobody has examined. A short one leaves a history where each step is a thing a person read and agreed with, which is the only version of this workflow that produces code a team is willing to own.
Read the diff rather than the summary of the diff. An assistant describing what it did is describing what it intended, and the two come apart in precisely the places worth catching: a default quietly changed, a condition inverted, an import added that drags something heavy in behind it.
The Orvain UI team
Writing about design systems and the tools that ship them.




