On this page
TL;DR
- I gave myself a hard two-hour timer to ship a real, deployable SaaS using only AI builders and AI-pair coding tools.
- Stack that won: Bolt.new for the scaffold, Cursor + Claude Sonnet 4.6 for iteration, Convex for the backend, Polar for billing, Vercel for deploy.
- It worked. The product is online, accepts payments, and has a real user (me, but still).
- What broke: auth at minute 47, the database schema at minute 73, and my pricing page typography at minute 110.
- Two hours is the new "weekend project." If you're not building this fast in 2026, you're optimizing the wrong loop.
The setup
I wanted to know how far AI could actually take me in a single uninterrupted session. Not "scaffold a todo app in 5 minutes" demos. A real SaaS — auth, database, payments, deployment, marketing page.
The product I picked: a tiny tool that lets podcasters generate clipped audiograms from a transcript timestamp range. It's narrow enough to ship, niche enough to charge for, and I had no existing code for it.
Rules I gave myself:
- Two-hour timer, no extensions.
- I write zero code by hand. Everything goes through an AI tool.
- It has to deploy publicly and accept a real payment.
- I document every minute so I can write this post honestly.
The first 15 minutes: scaffold
I started in Bolt.new. I described the product in a paragraph: a Next.js 16 app, login required, a single page where the user pastes a transcript, picks a start/end timestamp, uploads an audio file, and gets back a clipped MP3 with waveform burned in.
Bolt produced a working scaffold in about four minutes. The UI was generic but functional. Auth was stubbed (a fake login button). The audio processing was a TODO. The transcript paste box worked.
Honest read: Bolt is excellent at the first 80% of the front-end and consistently weak at anything stateful or backend-heavy. I expected this. I clicked "Open in StackBlitz," exported to a GitHub repo, cloned it locally, and switched to Cursor.
Minutes 15-40: real auth
I wired up Better Auth via Cursor + Claude Sonnet 4.6. I asked for "Better Auth with email/password and Google OAuth, integrated with Convex per the official Convex Better Auth alpha component."
Claude wrote it. It didn't compile.
The Convex + Better Auth integration is genuinely in alpha, the docs moved last month, and Claude's training data was slightly out of date. I pasted the current docs page into the conversation, asked Claude to fix the imports, and on the second try it built clean. Total time wasted on hallucinated APIs: about 8 minutes. This is the single most important meta-lesson — when you're working with anything bleeding-edge, paste the docs.
Auth working. Login screen exists. Sessions persist. On to the database.
Minutes 40-55: the schema
I described the data model in plain English. "Users have many Projects. Each Project has many Clips. Each Clip has a status, a source audio URL, a start time, an end time, and an output URL once processed."
Claude generated a clean Convex schema, a createProject mutation, a listClips query, a requestClip mutation that enqueues a job. It even added indexes on userId for both tables. Better than I'd have written by hand if I were rushing.
What broke: I asked Claude to add a status field as a union type — "pending" | "processing" | "ready" | "failed". Convex complained about the validator syntax. I copy-pasted the error back, Claude apologized, used v.union(v.literal(...)) correctly, and we moved on. Two-minute fix.
Minutes 55-90: the actual work
This is where every "build SaaS in an hour" demo quietly skips ahead. Real audio processing.
I asked for an FFmpeg-based clipping function deployed as a Convex action. Claude wrote it. It didn't work — Convex actions can run external Node, but the FFmpeg binary isn't there by default. We pivoted to calling out to a Replicate model that does waveform burn-ins. Claude rewrote the action to use the Replicate REST API.
This worked. First clip processed at minute 78. I cried a little.
Then I noticed: the Replicate output URL expires after a few hours. I needed to download it and re-upload to Convex storage. Claude added that logic. One typo (ctx.storage.store vs ctx.storage.generateUploadUrl) cost me three minutes.
By minute 90 I had: login, a real database, a working audio processing pipeline, output stored in Convex.
Minutes 90-105: payments
Polar.sh checkout via their Next.js adapter. I gave Claude the Polar docs URL and asked it to add a /pricing page with a single tier ($12/month for unlimited clips), a webhook endpoint that flips a paidUntil field on the user record, and a paywall on the clip generator.
It compiled. The webhook signature validation was wrong on the first try (Polar changed their header naming convention three months ago). I caught it because I always test webhooks before declaring victory. Five minutes of fix-and-retest and I had a real Polar checkout flow.
I made a real $12 purchase to my own account. The webhook fired. My paidUntil updated. The paywall lifted. I sat back in my chair, slightly stunned.
Minutes 105-120: deploy and polish
I pushed to GitHub. Vercel auto-deployed. The Convex production deployment was already wired (I'd done that in minute 16 with npx convex dev --prod). DNS was a domain I had lying around.
The marketing page from Bolt was hideous. I spent ten minutes asking Cursor to "make this not look like every other AI-generated landing page." Claude proposed a layout with a single hero, a 30-second demo video placeholder, three feature cards, and a pricing block. Better. Not great, but shippable.
At minute 119 I tweeted the link. At minute 120 I closed the laptop.
What broke (the unflattering parts)
Let me be honest about what didn't work, because the highlight reel hides a lot.
- Bolt's initial output. Pretty, functional, but I had to throw away maybe 30% of it once I knew what I actually wanted. Bolt is a great way to start a conversation about your UI, not to ship final code.
- Hallucinated Better Auth APIs. Lost ~8 minutes. The fix is always: paste real docs.
- Convex action runtime confusion. I assumed FFmpeg was available; it isn't. Five-minute pivot to Replicate.
- Polar webhook header naming. A platform change since Claude's training cutoff. The fix took five minutes because I tested the webhook explicitly. If I hadn't, this would be a silent production bug today.
- The landing page. AI-generated marketing copy still reads like AI-generated marketing copy. I'll rewrite it by hand this week.
- Mobile responsiveness. I forgot to check until minute 117. It's mostly fine but the timestamp picker is broken below 380px wide. On the list.
What I'd do differently
- Start with the data model, not the UI. Bolt's UI seduces you. The real product is the schema.
- Skip Bolt entirely if you have any taste. Just start in Cursor with a Next.js + Convex + Better Auth template. You'll save 20 minutes of UI re-work.
- Use a BYOK chat workspace as the planning surface. I kept Cursor for code edits and used NovaKit in another window to think through the schema, draft the pricing copy, and keep a running TODO. It's the difference between "vibe code" and "vibe code with a spec."
- Test webhooks immediately. Don't trust them until you've fired a real event end-to-end.
The stack that worked, ranked by value
- Cursor + Claude Sonnet 4.6. This is the engine. 70% of the work happened here.
- Convex. Schema, queries, mutations, actions, and storage in one place — no separate backend or DB to wire up. Saves 30+ minutes alone.
- Polar.sh. Easiest payment integration of any 2026 platform I've tried. Webhook quirks aside, it's a 15-minute job.
- Better Auth. Painful only because of the alpha Convex integration. The library itself is clean.
- Bolt.new. Useful for the first scaffold. Skippable if you have a template.
- Vercel. Deploy is two clicks. Always has been.
The meta-lesson
The "two-hour SaaS" used to be an aspirational tweet. In 2026, it's the actual workflow. Anyone with taste, the right stack, and the discipline to test as they go can do this.
What this means:
- Ideas are even cheaper to validate. If you can build it in an afternoon, you can run five experiments a month.
- The bar for "indie product" went up. Polished, deployed, paid is now the minimum. A scrappy MVP isn't enough — your competitor shipped a polished one in the time it took you to write your README.
- Distribution and taste are the only moats left. The build is solved. The hard parts are now: do you have an audience, and do you have judgment.
If you've been telling yourself you'd ship a side project "when you have time," 2026 is the year you've run out of excuses. The tools work. The cost is your weekend, not your savings.
For more on how this stack came together, see Vibe Coding in 2026. For why running everything through one BYOK workspace beats juggling a dozen subscriptions, see Consolidate Your AI Subscriptions.
Now go build something. The timer starts when you close this tab.
NovaKit is the BYOK AI workspace I use for planning and writing while I code in Cursor. Bring your own keys, route across every major model, keep your data local.