OTFotf
All posts

Lovable can spin up your MVP. It can't ship to production with you.

D
DaveAuthor
12 min read
Lovable can spin up your MVP. It can't ship to production with you.

A friend asked me last week why we built OTF instead of just using Lovable.

He's been on Lovable Pro for four months. The first three weeks felt like magic — type a prompt, get a deployed app, point at a domain. Month two he wanted Stripe. Month three he wanted to swap the auth library. Month four his Lovable bill was at $300, the codebase was a stranger to him, and the "MVP" still didn't have a buyer.

That's not a Lovable bug. That's the model working as intended. Lovable, Bolt, Emergent, risework — they're all great at the first 80%. They're structurally bad at the last 20%, which is also the part that decides whether the thing ships or rots.

I rebuilt his project with Cursor + an OTF kit in a weekend. Total cost: $149 once. He still has the Lovable subscription cancelled in his calendar.

But the cost isn't the interesting part. The interesting part is why the rebuild was a weekend instead of another four months — and what that means for anyone using vibe-coding tools to ship something real.

The Lovable bill, broken down

Public pricing as of May 2026:

  • Lovable Free — capped credits, watermarked deploys
  • Lovable Pro — $25/mo, ~100 credits/day
  • Lovable Teams — $30/seat/mo

Bolt is in the same shape:

  • Bolt Pro — $20/mo, plus per-token overages above the included quota

ShipFast and similar paid boilerplates take a different shape — one-time payment, no subscription:

  • ShipFast — $299 once
  • Makerkit — $299–699 once depending on tier

The math people don't run before signing up:

ToolYear 1Year 2Year 3
Lovable Pro$300$600$900
Bolt Pro*$240+$480+$720+
ShipFast$299$299$299
OTF kit$149$149$149

*plus token overages, which are real and cumulative.

A subscription tool isn't expensive in month one. It's expensive in month thirty-six, which is when the project that didn't ship at month four is now definitively not shipping.

But focusing on the price tag misses the point. The bill is the symptom. The thing causing it is structural.

Sandboxed agents can't follow you to production

Lovable, Bolt, Emergent, risework — they all run inside a sandbox they own. Their VM, their database, their deploy pipeline, their conventions. That's the entire premise: you don't have to set anything up because they've set everything up for you.

This is great for a hello-world. It's a wall at week three.

What sandboxed agents can't do, in roughly the order you hit them:

  • Read your existing repo. They see only the project they generated.
  • Follow your conventions. They enforce theirs — naming, folder layout, the auth library they chose.
  • Plug into your MCP servers. No Postgres MCP, no Stripe MCP, no GitHub MCP. The agent doesn't even know your DB exists outside the one row it generated.
  • Run your test suite. Or your deploy script. Or anything in your package.json they didn't write.
  • Use custom skills. No /otf-arch, no /otf-blog, no /otf-plane. The skill mechanism is in your IDE, not their browser tab.
  • Survive when you swap a library. "Replace Better Auth with Clerk" is the prompt that breaks every sandboxed tool, because the rest of their generated code stops being internally consistent.
  • Stop burning tokens on basics. Every session, they regenerate the auth flow from scratch. You pay for it again.

File-system agents — Claude Code, Cursor — don't have any of these limits. They live in your repo. They read every file. They follow your CLAUDE.md, your .cursorrules, your ai/prompts/. They run your scripts. They use your MCP servers. They can swap a library because they can read what depends on it.

The catch is that file-system agents need context to work well. Drop them into an empty repo and they hallucinate exactly the same way Lovable does — they invent conventions that don't exist.

That's where kits come in.

What kits actually ship — beyond the code

The thing nobody outside this market understands: a kit isn't a code dump. The code is maybe 40% of the value.

What ships in an OTF kit:

my-saas/
├── src/                          ← the boring 80% pre-built
│   ├── auth/                     ← Better Auth wired
│   ├── billing/                  ← Stripe + webhooks
│   ├── db/                       ← Drizzle schema, migrations
│   └── ui/                       ← @otfdashkit/ui components
├── ai/
│   └── prompts/                  ← 40+ tested prompts
│       ├── add-entity.md
│       ├── add-screen.md
│       ├── add-auth-flow.md
│       └── ...
├── .claude/
│   ├── CLAUDE.md                 ← your project context, pre-tuned
│   └── skills/                   ← otf-arch, otf-blog, otf-plane
├── .cursorrules                  ← Cursor mirror
├── scripts/
│   ├── setup-domain.sh           ← custom domain in one command
│   ├── deploy-railway.sh         ← idempotent prod deploy
│   └── ...
└── docs/
    ├── stripe-setup.md           ← walkthrough, not "see Stripe docs"
    └── launch-checklist.md       ← go-live gates

That .claude/ directory is the part Lovable can't replace. It's the difference between Cursor knowing what your project actually is and Cursor guessing. When my friend's rebuild took a weekend instead of four months, this is most of why.

Cursor + the kit's CLAUDE.md had the same context Lovable's sandbox had — but file-system-native. Every prompt I wrote referenced the existing types. Every change I asked for landed in the right file with the right conventions. Every test passed because the prompts were tuned to the kit's stack.

That's not magic. That's pre-baked context.

What "shipping to production" actually requires

Founders use the phrase "shipping to production" loosely. It usually means "I deployed it to a URL." That's not shipping. Shipping is the entire list:

  • Custom domain — DNS records pointed, SSL verified, the URL your buyer types
  • Production env vars — Stripe live keys, OAuth secrets, real database, no test data
  • Stripe set up correctly — products created, webhook signing secret rotated, the right tax mode
  • Deployment that doesn't break on every push — tested deploy script, healthcheck wired, restart policy
  • App Store / Play Store submission (if mobile) — Apple Dev account, screenshots at every required size, content rating questionnaire, the privacy form
  • SEO basics — sitemap, robots.txt, OG tags, meta descriptions per page
  • Email transactional flows — at minimum: sign-up confirmation, password reset, payment receipt
  • Error monitoring — something other than console.log

This is the "boring 80%" that's not boring at all when you're three weeks deep with no income to show for it. Every item on that list is a dragon for someone who hasn't shipped before. Vibe-coding tools mostly hand-wave it: "we'll deploy for you" usually means "we'll host it on our subdomain with our DB on our infrastructure" — which is fine until you want a real domain, your own DB, or to leave.

OTF kits ship with concrete scripts and walkthroughs for every item on that list. Not "see the docs". Concrete. The kit goes from clone to a paying customer's URL with a real Stripe webhook firing on a real domain in roughly a weekend, if you've never done it before. In an hour, if you have.

That's what "ship to production" means. The entire arc of it. Sandboxed tools build the part that's easy to demo. Kits build the part that's easy to demo and the part that decides whether you have a business.

Why one-time pricing is the right shape for this

Subscriptions price usage. They make sense when usage is the cost — you pay Vercel for compute, you pay Stripe for transactions, you pay Postgres for storage. The vendor's costs scale with yours.

Vibe-coding subscriptions price generation. The vendor's actual cost — the LLM tokens they're forwarding to Anthropic or OpenAI — does scale with usage. But the value a buyer gets from regenerated boilerplate doesn't. Generating an auth flow for the hundredth time isn't a hundred times more valuable than generating it once.

A kit prices the work once. We've already paid the tokens to write the auth flow correctly. We've already debugged the Stripe webhook. We've already read Apple's submission rules. You pay for that work — once — and you own the source after.

The math we used to land at $149 launch / $249 bundle:

  • A subscription that pays itself off vs Lovable Pro in five months ($149 ÷ $25/mo)
  • A floor low enough for a side project but not so low it signals "free trial"
  • Public milestone hikes after every 100 / 250 / 500 sales — real scarcity, no fake countdown

If pricing is a question of what model fits the value, ours is one-time-licensed code, period. Subscriptions belong on tools that scale with you (your DB, your CDN, your Stripe). Tools that hand you boilerplate should hand it to you and step out of the way.

What you actually do with Cursor + a kit

This is what the day-to-day looks like, end to end:

# Clone the kit (license-keyed download — runs locally, no vendor lock-in)
gh repo clone otf-kit/saas-dashboard my-saas
cd my-saas
bun install
cp .env.example .env.local  # fill in Stripe + DB

# Wire your domain
./scripts/setup-domain.sh mydomain.com

# Open in Cursor — CLAUDE.md + .cursorrules are already there
cursor .

# Now everything you'd normally ask Lovable, you ask Cursor:
"Add a Pricing screen with three plans, monthly/annual toggle, Stripe checkout"
"Wire a magic-link signup with Better Auth"
"Add an admin route for viewing all signups"

# Deploy when ready
./scripts/deploy-railway.sh

The prompts above are the same prompts you'd give Lovable. The difference is they land in your repo, follow your conventions, run your tests, use your MCP servers, and survive across sessions because Cursor has the project's full file tree as context.

No browser tab to maintain. No subscription to renew. No vendor sandbox to escape from when you want a real domain.

I tested it: adding Stripe checkout in three prompts

Talking about the workflow is one thing. The thing that convinced me my friend was right to switch was watching it happen on a real codebase.

The kit ships with a Pricing page wired to a generic Checkout — fine for a starter, wrong if you're shipping a SaaS with three plans, an annual toggle, and a coupon flag for the founding-100 launch. So I asked Cursor to fix that.

Prompt 1 — replace the generic checkout with three real plans:

Replace the existing Pricing page with three plans (Starter, Pro, Team), monthly/annual toggle, and a coupon support if a ?promo= query param is set. Pull plan IDs from the existing Stripe products in lib/stripe/plans.ts. Match the visual style of the rest of the kit — use the existing PriceCard component from @otfdashkit/ui.

What Cursor did, in order, in roughly 90 seconds:

  1. Read lib/stripe/plans.ts (which the kit ships with — three placeholder products), saw the schema, kept the existing typing
  2. Read apps/web/app/pricing/page.tsx, identified the generic checkout, planned the rewrite
  3. Read @otfdashkit/ui exports for PriceCard, used the existing component (didn't reinvent)
  4. Wrote the new page with billing-period state, Stripe coupon hand-off via ?promo=, and the brand voice from the kit's CLAUDE.md ("Get the kit →", not "Buy now")
  5. Updated the Stripe webhook handler in app/api/stripe/webhook/route.ts to handle the new line items
  6. Ran bun run typecheck — 0 errors

It worked. First try.

Prompt 2 — wire the founding-100 sold count:

Add a /api/pricing-state route that returns the count of completed Stripe checkouts in the last 30 days. Surface it in the Pricing header as "Founding-100 pricing — N spots left at $149". Disable the founding-100 framing when count >= 100.

Cursor noticed the kit already had a Drizzle buyers table (kits ship with it) and used db.select({ count: sql\count(*)` }).from(buyers).where(...)`. Type-safe count. Cached the result for 60s in-memory because hammering Stripe on every Pricing pageview is rude. Added a CSS transition so when the count updates the number animates.

Prompt 3 — add the magic-link signup the buyer flow needs:

The kit's auth flow uses Better Auth with email/password. Add a magic-link option as the default — keep email/password as fallback. Use Resend for the magic-link email; the kit's transactional template at lib/email/templates/welcome.tsx is the visual baseline.

Cursor read the Better Auth config, the existing welcome template, the Resend setup. Generated the magic-link plugin config, the new email template (mirrored the welcome one), the route handler. Tested locally with stripe listen and bun run dev. All three prompts. Forty minutes total.

Lovable cannot do this. Not because of the LLM — Lovable uses Claude under the hood for a lot of its generation. It's because Lovable's sandbox doesn't see lib/stripe/plans.ts. It doesn't see @otfdashkit/ui. It doesn't see the existing Drizzle schema. Every prompt to Lovable is a fresh start with no context. Cursor with the kit had three prompts of cumulative context, and used all of it.

That's the wedge. That's the entire wedge.

What you're actually buying

The subscription tools are selling you generation capacity. Kits are selling you the part of the project that's already done.

Both are real value. They're optimised for different stages of the work. Lovable, Bolt, Emergent are great at the first conversation — the moment you have an idea and want to see it on a screen. They're structurally wrong for the moment your idea has a buyer who needs a working Stripe webhook on a custom domain by Friday.

OTF kits aren't trying to replace that first conversation. They're trying to replace the second one — the one where the dream meets the deploy script.

If you're at the second conversation, the math is straightforward. $149 once for code you own, with the agent context that lets Cursor actually finish the job. The first conversation is free anyway — you can have it with Lovable's free tier or with bun create.

The thing we kept hearing from people who paid us first was: "I just want the boring 80% to be done."

So we did it.

Live demos: saas.otf-kit.dev · fitness-preview.otf-kit.dev. Click around — see what the kit ships with before you decide whether $149 is worth it. The whole pitch is right there in the demo. If it's not, don't buy.

ai-toolslovablecursorkitsannouncement

On this page