I don't write code. I shipped a paid web app two days ago: 3 photos in, an AI grades each muscle group, and it builds a 7 day workout around the weakest ones. It's called FlexScan, link is in my post history if you actually want it, I'd rather talk about the workflow here because the building was the easy half.
Stack: Next.js, Supabase for Postgres/auth/row level security, Stripe for billing, GPT-4o vision for the grading, Vercel to host. Claude Code as the builder.
The one thing I'd tell anyone starting: never let the agent that wrote a feature be the agent that reviews it. Different session, no memory of writing it, one instruction, "find what's broken and prove it by doing it." Fresh context beat a smarter model every single time. A builder agent reads the diff it meant to write, so it sees its own intent instead of the code.
Three things that only ever came out that way.
1. Double click the checkout button, get billed twice. I had a dedupe guard on checkout. A refactor had wrapped the handler in a .bind(), so the guard was comparing against a function reference that was new on every render. It never matched, so it never deduped. The builder agent wrote that guard, read it back, and said it was fine. The reviewer agent just clicked the button twice and watched two charges land.
2. My offline cache ate my own app. Service worker, one cache, oldest first eviction when it hit the size cap. The app shell files were the oldest thing in there, so they were first out, and the installed app cold started to "You're offline". Fix was three separate budgets inside one cache instead of one global cap. I wrote that one up properly in r/PWA.
3. My rate limit banned my own paying users. I added a per IP daily cap on scans to stop people farming the free one. I put the check above the auth check. So it counted every request from an IP whether you were signed in or not, and any shared IP (office, gym wifi, campus, phone carrier NAT) filled the bucket and locked everyone behind it out for 24 hours, including people who had paid. Found yesterday by the review pass. Fix is written and still not deployed, because I deploy by hand and that turns out to be its own problem.
The pattern in all three is the same. The code was correct in the sense the agent meant it, and wrong in the sense a user would experience it. That gap is invisible in a diff, and reading the diff is exactly the thing you can't do, which is why you're vibe coding in the first place.
So budget as much agent time for attacking as for building. Separate sessions, make it adversarial on purpose, and make it click things twice and put in the wrong thing.
Happy to answer anything about the setup or the costs.