Claire Mull — How I use Claude
Me + Claude

It started as vibe coding.

The more I use Claude, the less that's true.
Claire MullProduct / UX DesignerNYC
request spec build test runs/makeit-swipe-deadspaceFAIL → PASS

Learning to ship.

I'm a new designer who decided to learn to ship. I came in with almost no coding background, so I had Claude Code walk me through the frameworks first. Every build teaches me more of them, and every bit I learn closes another blind spot. That is how I start catching the errors and data loss Claude misses on its own.

I don't ship what I can't explain.

A few core functions from my How bakebook works doc.
An adjustable calculator that weighs the full breadth of bakebook's costs.
runsaving butter chats
VERDICT: PASS

Loops made Claude's fixes trustworthy.

Here's what they look like, and how they work.

A loop is a cycle that runs one change through the same steps, on its own. I describe the change I want (a spec), and Claude writes the code. Then a separate helper tests it: it opens the real app and checks whether the change actually works. If it doesn't, the cycle repeats until it passes, or I step in.

requestI ask for a change specthe change, written out buildClaude writes the code testchecked on the real app ↺ FAIL → build
Builder
gets my spec and writes the code.
Tester
gets the spec only, never the code. judges the change on its own, so a pass isn't Claude grading itself.
the lapsaving butter chats
iPhone / WebKittest account

In an update, some of the app's stored data got wiped. My recipes came back, because they live in the cloud. But my chats with butter, my baking assistant, were gone. They had no cloud copy.

Does a saved chat survive a reinstall? You can't read that from the code, so I ran it as a loop. The tester saved a chat, cleared everything, and reloaded. It did not come back. A permission rule was missing on the backend. I fixed it, ran the loop again, and this time the chat survived.

It even flagged one check it couldn't finish, instead of calling it a pass.

The PASS, on my real app. After a full storage wipe and reload, the saved chat is restored from the cloud.

I test in a sealed copy.

Testing a live app is dangerous. One bad run can corrupt real users' data, or an account that's under review. So I test in a sealed copy, and nothing a test does can reach a real user.
Live appreal usersproduction data
The sandboxa sealed copy of the app
The harness

A real-size browser drives the app, so the test sees what a user sees. It runs the exact bytes I'd ship, no build step in between, and in a loop it points at a dev branch, not the live app.

The sandbox

Every test signs in as a throwaway account, never a real one or an account under review. Fake data is seeded into the browser's storage, and writes to the live database are blocked.

✕ no writes escape
A test proves what a user sees, not that the code is right. That's why the tester stays separate, and why interaction fixes still get confirmed on a real device.

Guardrails & security.

Main examplethe AI assistant I shipped
It's easier to call AI straight from the app, with the key sitting in the browser. But that lets a user read the key, swap the model, rewrite the prompt, or run up the bill. So I put the AI behind a server I control. The client sends a message and nothing else.
The app
sends a message, nothing else
The server I controlevery request passes here
Control

Model, prompt and reply length set here, never the client. Only two models allowed, anything pricier refused.

Cost

A daily limit per user, a token ceiling per reply. Heavy users step down to a cheaper model. Cost capped by design.

Abuse

A fast model screens every message before the real one answers. Repeat offenders get a strike, then a ban.

Claude
never reachable directly; no key in the browser

Pushback — saying no to Claude

>no
Claude has biases, and strong built-in patterns. They're a jumping-off point, not a final answer. If you're not pushing your own agenda and saying no to it, you're missing a lot, and you've handed over your control and your judgment.
A few examples
Problem-solving
Claude proposed: ship the swipe fix, the tests pass  
A gesture isn't fixed until I feel it on a real phone.
Claude trusts a green check: the tests pass, so ship. But interaction tests are synthetic, a script tapping the screen, not a thumb. A real finger sends signals a script never does, so a gesture can pass in the harness and still feel broken in your hand. So I made it a rule that anything you touch gets confirmed on a real device, and it caught fixes that would have shipped broken.
Judgment
Claude proposed: move free users to a cheaper, weaker model  
The free tier is the sales pitch. It stays on the good model.
Claude optimized the number in front of it, cost, and the cheapest fix was to weaken the free experience. But the free tier is what sells the app. Weaken it and no one upgrades; the saving quietly kills the funnel. I said no, and everyone stays on the good model.
And the biggest step up from vibe coding is actually designing.
I pick the fonts and the colors, and bring my own icons and assets.
ideation whiteboard
Whiteboardplanning tools & components
Figma design, recipes screen
Figma design, add-ingredients screen
Figma design, recipe screen
Human designed in Figmaa flow, bakebook
Illustrator layout
IllustratorBlackbox layout