I built the app before I designed it
It worked. That was the problem.
I wanted a cashflow tool for contract work, so I built one. Not a prototype. A real app, in Claude Code, working end to end before I had drawn anything. Runway exists because of that, and it does the job.
Then I went back to design it, and got stuck.
Designing something that has already been built
The app had been built from screenshots. I would describe a screen, look at what came back, and adjust. It got me somewhere fast, and it left me with nothing to change. No tokens. No components. No source of truth. Just a lot of screens that happened to look similar.
So every design decision I wanted to make afterwards was a search-and-replace across files, and every one of them could be undone the next time I asked for a change. Move a colour and you are moving it everywhere it was typed, hoping you found them all.
That is the part worth saying out loud, because it is where a lot of AI-assisted work is heading right now: the speed is real, and it is borrowed against a system nobody built. Design after build is not design. It is repair.
So I built the process backwards on purpose
I wanted to see what it looked like if the design came first and the code came out of it. Figma has an official route for that, Code Connect, but it is an Enterprise feature and I am on a Pro plan. So I built my own to find out what it would take.
A component is read straight out of Figma and captured as it is. I write the rules for how that component becomes code. The code comes out bound to tokens, and a check runs over it: does every value resolve, has anything been guessed, does it match what Figma said. If not, it fails and I fix the rules rather than the output.
Nineteen components went through that loop: buttons, cards, form fields, icons, and a working login screen built out of them. They are running here, generated rather than hand-built.
I had planned to write a lot more software than I did. Most of the stages I expected to build turned out to be a conversation rather than a program. The model does the interpreting, and writing my own worse version of that would have been busywork.
What did need to be real code was the checking. That is the part you cannot leave to a model that is trying to be helpful.
The tooling is not the transferable part. These four rules are, and they hold whether or not there is a model in the room:
- Decide where the truth lives before you start. One place holds the values. Everything else points at it.
- Never let a value be typed twice. If it appears in two files, it will disagree with itself eventually.
- Flag what you do not know. Anything the rules do not cover should fail loudly, not get filled in with something plausible.
- Make accessibility a value, not a review. A minimum tap target is a token. A review is a person remembering.
Runway is finished and I still use it. The pipeline is proven and paused: a method with a playbook behind it, not a product, and I am not going to pretend otherwise. Blocks came out of the same habit of shipping something small to find out whether the idea survives contact.
The open question I have not answered: how much of this survives when it is a team of eight rather than one person with an opinion? That is the version I would like to try next.