I built the first working version of my SaaS in a weekend with Claude and Next.js. That sentence is true, and it's also the least interesting thing I can tell you about the weekend.
The genre this headline belongs to is mostly a lie — not the "I did it" part, the implied part. "Weekend SaaS" posts sell you the fantasy that the hard thing is production: that if you could just type the code fast enough, you'd have a business by Monday. So they show you the scaffold, the pretty landing page, the Stripe button, and they stop exactly where the real work starts. The typing was never the hard part. The machine made that obvious by doing most of it while I watched.
So this is the other breakdown. The honest one. It's a story about one clean, green, perfectly-typed diff the model handed me on Sunday afternoon that would have quietly eaten a paying customer's money — and the one change to how I work that caught it. That change is the whole product now. The weekend just taught me what it was.
What actually happened, hour by hour, with no flexing
Let me get the "breakdown" people clicked for out of the way, because it's genuinely short.
Friday night was scaffolding, and it was stupid fast. create-next-app, the App Router, Tailwind, a Postgres instance, auth wired through a provider, the schema for the core objects. Claude wrote most of it and I steered. The stuff that used to be a Saturday of yak-shaving — config, boilerplate, the fourteenth time I've set up the same middleware — compressed into a couple of hours of me describing and the model producing. This part of the hype is real. Setup is solved.
Saturday was the actual feature: the one thing the product does that's worth paying for. Here the rhythm changed. I'd describe a slice, the model would produce a confident, plausible, well-structured implementation, and I'd spend most of my time reading it rather than writing it. Not reviewing in the "LGTM" sense — reading it the way you read a diff from a very fast junior who is never, ever unsure of themselves. Most of it was good. Some of it was good-looking and wrong, and the ratio is the entire story of building this way.
Sunday was supposed to be payments and polish. It became the reason this post exists.
The diff that looked perfect
Sunday afternoon I asked for the webhook handler — the thing that receives the payment event and updates the account. The model gave me back exactly what you'd want to see. Typed end to end. Idiomatic. Error handling in the right places. It even added a comment explaining the retry semantics, which is the kind of thoughtful touch that makes you trust the author. It compiled, it passed the test it had helpfully written for itself, and it read clean.
It acknowledged the webhook before it persisted the row.
If you've never been burned by that line, it looks like nothing. The handler returns its 200 OK to the payment provider, and then writes the record to the database. 99.9% of the time those two things happen microseconds apart and you never notice. But the provider retries on anything that isn't a fast 200, and the write can fail or lag — and on the one bad night where the ack goes out and the save doesn't land, the provider sees success, never retries, and you have a customer who paid you with no record that they did. Locked out of the thing they just bought, nothing in the logs to say they were ever there.
I know this bug in my body. I shipped it years ago, on a different product, with no AI anywhere near it — a clean write path that acked before it persisted, and a phone call I can still feel from the customer it locked out. So I recognized it on sight. That's the only reason I caught it. The model didn't flag it, because nothing about the code looks wrong — it looks like the work of someone careful. The bug isn't in the syntax. It's in the ordering, and the ordering reads fine.
Here's the part that should bother you more than it bothered me in the moment: two lines reordered. That's the fix. The most dangerous diff of the weekend and the cheapest to repair — if, and only if, someone in the loop was actively asking "what happens on the retry?" instead of admiring the clean code.
The thing I changed — and it's not "review the AI's output more carefully"
The obvious lesson is "read what the model writes." True, useless. I did read it. I caught this one because I'd personally been set on fire by it once; I will not catch the next one that burned somebody else. "Be more careful" is not a system. It's a hope, and hope doesn't scale past the bugs you happen to have scar tissue for.
The real lesson is structural, and it's embarrassingly simple:
The thing that writes the code cannot be the thing that blesses the code.
When I ask one model to produce a diff and tell me if it's safe, I'm asking the author to grade their own homework, in the same confident voice they use for everything. It wrote the ack-before-persist handler and it would have told me the handler was correct, because from the inside of "I just produced this," it is correct — it compiles, it matches the request, it looks like care. Self-assessment is exactly the thing an eager author is worst at.
So I stopped doing that. Now the model that generates the diff is never the one that signs off on it. There's an author pass whose job is to produce — fast, cheap, endless, genuinely great at the thing that got easy. Then there's a separate skeptic pass whose entire job is to try to break that diff rather than admire it — prompted not for "is this good" but for "here is a diff, find the input that makes it lose money." Asked that way, about that handler, the retry case is the first thing it reaches for. And then there's a human on the merge button — me — who owns the call and can see the blast radius neither pass can, because I'm the one who knows a locked-out customer is a phone call and not a log line.
Author, skeptic, human. The author has infinite throughput and I've learned to measure it by almost nothing. The skeptic produces zero code and it's the most valuable seat in the system. That's not a philosophy I read somewhere — it's the shape the weekend beat into me, when the author handed me a beautiful diff that would have cost me a customer and had no idea it had done anything wrong.
What a weekend actually buys you (and what it doesn't)
Since I'm being honest about the rest of it: a weekend gets you a prototype that proves the core loop works. It does not get you a business. By Sunday night I had a thing that did the one valuable action end to end, for me, on my machine, with my data. That's real and it's worth something — it's the difference between an idea and an artifact you can put in front of a person.
What the weekend did not produce, and what no weekend produces: the error states, the empty states, the "what happens when the input is garbage," the billing edge cases, the abuse vectors, the onboarding, the second user who doesn't think like you, the thing that stays up at 2am. That's not weeks of work, it's months, and it's most of the actual product. The machine compressed the part that was already the easy part and left the hard part exactly as hard as it always was — arguably harder, because now there's more confident, plausible code to be wrong in.
So when you read "I built a SaaS in a weekend," translate it to "I built a convincing prototype of the core loop in a weekend, and the machine made the typing cheap enough that I could spend the whole time on whether the thing was right instead of whether it existed." That's the actual gift. It's smaller than the headline and much more useful.
Why that weekend is the entire architecture of what I build now
That near-miss on Sunday wasn't a footnote to the project. It became the project.
The thing I'm building, xenition, is an agent platform, and the whole industry right now wants to cheer for the part that produces — look how much it ships, look how clean, look how fast. But a generator is just doing the skill that stopped being scarce, at a scale no human can match, and then signing off on its own work in the same even voice whether the diff is a masterpiece or the handler that eats a payment. So the entire shape of the product is the thing my weekend taught me: never let the author bless its own output. An author that generates, a skeptic whose only job is to attack what the author made, and a human who owns the merge. The abundant thing, the scarce thing, and the person accountable for the call.
I didn't set out that weekend to find a product architecture. I set out to see how far Claude and Next.js could get me by Monday. The answer was: all the way to a working prototype, and one reorder-two-lines bug away from shipping a disaster that looked exactly like success. Which turned out to be the most valuable thing the weekend could have shown me.
Top comments (2)
That webhook story — acking the 200 before the write, fixed by two lines reordered — is the scariest-cleanest bug anecdote I've read in a while, and the author/skeptic/human split is one I'm stealing for my own reviews.
Steal away — that's what it's for 😄 The part that surprised me most: the skeptic pass adds almost no friction once it's a separate step. The hard bit was psychological — admitting the model that just impressed me shouldn't also be the one I trust to bless it. If you try it, that one question — "what happens on a retry?" — punches way above its weight. Would love to hear how it lands in your reviews.