Skip to content
BlackFig
LaunchingComplete guide

From prototype to product: launching an AI-built app properly

AntPublished 14 min read

In short

To turn a prototype into a product, get the code into a GitHub repository you own, separate development from production, take payments through Stripe webhooks rather than a success page, add a few analytics events and the UK GDPR basics, then launch to a small group first and fix what they find.

On this page
  1. In this guide
  2. Prototype, MVP and product
  3. Decide what you are launching
  4. Own your code
  5. Choose where it runs
  6. Separate development from production
  7. Take payments properly
  8. Measure what users do
  9. UK GDPR basics
  10. Launch week
  11. Your first 100 users
  12. Scaling, or starting again
  13. Getting help with the launch

In this guide

You have a prototype that works. Maybe you built it in Lovable, Bolt, v0, Cursor or Replit, and people you show it to get it straight away. This guide covers what happens between that moment and strangers paying you, in the order I would do it.

If something in the app is already broken, fix that first. My guide to fixing a vibe-coded app covers security, data, speed and the rest. This guide assumes the core works and you want to go live properly.

Prototype, MVP and product

These words get used interchangeably, but they describe different jobs.

A prototype proves the idea makes sense. It only has to work for you, on your laptop, with tidy test data. AI builders are brilliant at this, and getting here is the hard first step.

An MVP is the smallest version real users can rely on. It does one job well, for one kind of user, and it can take money.

A product is an MVP that keeps working while you are asleep. Strangers sign up without your help, pay, trust you with their data, and come back the next day to find everything where they left it.

The gap between the first and the last is mostly invisible work: who can see what, what happens when a payment fails, where the backups are, and what the app does on a bad phone signal. None of it shows up in a demo, which is why prototypes feel closer to launch than they are.

I go into the difference in more depth in prototype vs MVP.

Decide what you are launching

Before touching hosting or payments, write down what version one is. One page is enough:

A one-page launch spec

  • Who it is for, in one sentence. Not everyone: the first kind of user you will actually talk to.
  • The one job it does for them, and how you will know they did it.
  • What they pay, when, and what happens if they stop paying.
  • What is out of scope for launch, written down so nobody builds it by accident.
  • What data you collect about them, and why you need each piece.
  • What has to be true before you invite the first stranger in.

This page does more work than it looks like. It tells you which screens to finish and which to hide. It tells you what your payment code has to handle. It is also the first thing a developer will ask for if you bring one in, and the clearest brief you could give an AI tool.

For a fuller version, use my product spec template. If you aren't sure what belongs in version one, the free MVP scope tool walks you through it.

Own your code

A product needs code that lives somewhere you control, with a history of every change. In practice that means a GitHub repository in your name. Every major AI builder can get you there, but each one works differently, and each leaves something behind.

Getting code out of each AI builder
How to exportWhat to watch for
LovableTwo-way Git sync on any plan. A zip download on paid plans.Connecting always creates a new repository. The database exports separately, without stored files, Edge Function code or secrets.
BoltTwo-way GitHub sync. Bolt checks for outside changes every 30 seconds.Only the project owner can connect. Disconnecting is permanent from your side, and branches can only be merged in GitHub.
v0A private GitHub repository, with a working branch for each chat.Publishing merges a pull request into the base branch. Deleting the repository can make the code unrecoverable.
ReplitThe Git pane, with auto-sync for two-way changes, or Download as zip.Copying a project leaves behind its secrets, database and deployment settings.

Cursor is the exception: it works on a repository you already have, so the code is yours from the start.

Two-way sync is useful. A developer can fix code in GitHub while you keep prompting in the tool. The catch is that your next prompt can quietly undo their fix, so agree which files the AI tool should leave alone.

Once the code is in GitHub, check that it actually stands on its own. Clone the repository onto a different machine and try to run it from scratch:

git clone https://github.com/your-name/your-app.git
cd your-app
npm install
npm run build

If the build fails, find out why now, not on launch day. The usual culprits are environment variables that only existed inside the builder, packages installed in the tool but missing from package.json, and a database that the code expects but the repository doesn't describe.

While you are there, add a file called .env.example that lists every environment variable the app needs, with the names only and no values. It is the single most useful document for anyone who touches the code after you, including you in six months.

The step-by-step guides are here: exporting AI-built code covers the general process, and the tool pages cover the details for exporting Lovable code, exporting Bolt code, exporting v0 code and exporting Replit code. If you are moving from a no-code tool rather than an AI builder, read moving from no-code to code.

Choose where it runs

The first hosting question is whether to leave the builder at all. My honest answer is usually not yet. Each of these tools can host a production app, and moving early adds risk without adding customers. What matters is knowing how your app is hosted, so nothing surprises you.

Lovable. Projects created from 13 May 2026 are server-rendered with TanStack Start and deployed as a Cloudflare Worker. Older projects are React and Vite single-page apps served as static files. My guide to taking a Lovable app to production covers domains, limits and when to leave.

Bolt. New projects publish to Bolt hosting by default. You can switch to Netlify, but Bolt's docs are clear that Netlify can't host a database or a traditional backend, so anything with a database should stay on Bolt hosting. My guide to taking a Bolt app to production covers the rest.

v0. Projects deploy to Vercel. With GitHub connected, each chat's working branch gets its own preview, and publishing merges into the base branch and waits for the production deployment. Environment variables are managed in Vercel.

Replit. Published apps run on one of four deployment types. Autoscale is the default, scaling with traffic. Reserved VM runs on a dedicated machine that never sleeps. Scheduled runs a job on a timetable and has no public URL. Static serves files with no backend, and Replit says it doesn't work for apps built with its Agent, because those need a server.

Your own hosting. If you do move a Next.js app to Vercel, two details catch people out. First, Vercel's fair use guidelines restrict the free Hobby plan to non-commercial personal use, and any way of taking payment from visitors counts as commercial, so a paying product needs the Pro plan. Second, changes to environment variables only apply to new deployments, so after you change a key, redeploy.

When moving does make sense

There are good reasons to move, and they are usually specific:

  • A team is joining. Developers will want a conventional setup they can run locally, with their own preview environments and a review process.
  • You need something the platform can't do. Long-running background jobs, a particular region for your data, or a service the builder doesn't connect to.
  • Costs stop making sense. Compare like for like, including the time it takes to run the new setup yourself.
  • You need everything in your own name. Investors and acquirers will ask who owns the hosting, the database and the domain.

If none of those apply, stay put and spend the time on customers. When you do move, move one piece at a time: code first, then hosting, then the database last, because the database carries the most risk.

For the tool-specific deployment steps, read deploying v0 to production and deploying Replit to production. For the bigger question of whether and when to leave, read moving off Lovable and Bolt hosting.

Separate development from production

In a prototype, there is one of everything: one database, one set of keys, one version of the app. A product needs at least two, so you can try a change without breaking it for paying users.

Some tools do this for you. Replit gives every published app a production database separate from the development one, each with its own DATABASE_URL, and keeps production secrets in the publishing settings. Structural changes you make in development are applied to production when you publish, so treat every publish as a database change and check it first. Replit also keeps the preview separate from the live app, so you can keep working without changing what users see until you publish again.

Whatever the tool, a few habits make the split work. Keep a set of test accounts in development, one for each kind of user, so you can check access rules quickly. Never copy real customer data into development to debug something; Replit's own docs say to copy development data into production only if it is safe for your live app, and the reverse deserves the same care. Use Stripe's sandbox keys everywhere except production, so a test purchase can never take real money.

If your app uses a Supabase project you manage, check these before launch:

Supabase before launch

  • Plan: Free plan projects are paused after low activity over 7 days. Paid projects are never paused for inactivity.
  • Backups: Pro projects get daily backups kept for 7 days. Free plan backups can't be downloaded, so export with the Supabase CLI if you stay on Free.
  • Files: Storage objects are not included in database backups. Back up anything users upload separately.
  • Point-in-Time Recovery: an add-on for paid plans, with a worst-case recovery point of two minutes. Supabase recommends it for databases over 4 GB.
  • Email: the built-in sender is limited to 2 auth emails an hour. Set up your own SMTP provider before launch, and turn off its link tracking.
  • Redirect URLs: add your production domain to the Redirect URLs list, with an exact path, so confirmation and reset links open the live site.
  • Row Level Security: enabled on every table in an exposed schema, with policies that limit each row to its owner.

I cover growth-stage infrastructure in scaling an MVP, and every pre-launch check in one place in the app launch checklist.

Take payments properly

Payments are where a prototype most often looks finished and isn't. The checkout works, the success page appears, the account upgrades. Then a customer closes the tab before the redirect, and you have their money and they have a free account.

Stripe's documentation is blunt about this. You can't rely on fulfilment from the checkout landing page, because customers aren't guaranteed to reach it. Webhooks are required if you sell subscriptions or accept payment methods that confirm later. The landing page is still useful, but only as a second, faster route to the same fulfilment code.

What a solid Stripe setup looks like

Use Stripe Checkout or Payment Links rather than building your own card form. Then make one fulfilment function on the server and call it from two places: the webhook, and the landing page. Stripe says that function must be safe to call more than once, even at the same time, for the same Checkout Session. For one-off payments, listen for checkout.session.completed, plus checkout.session.async_payment_succeeded if you accept payment methods that settle later.

Stripe also says the same event can arrive more than once and events can arrive in any order, so record the event IDs you have handled and don't assume one event always comes before another. In live mode, Stripe retries failed deliveries for up to three days.

Here is the shape of a webhook handler in a Next.js app, using Supabase for storage:

// app/api/stripe/webhook/route.ts
import Stripe from "stripe";
import { createClient } from "@supabase/supabase-js";
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); // check against your stripe-node version
// Server-only client using the Supabase secret key: never import this file into a component
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SECRET_KEY!);
 
export async function POST(request: Request) {
  const body = await request.text(); // the raw body, exactly as Stripe sent it
  const signature = request.headers.get("stripe-signature") ?? "";
 
  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(body, signature, process.env.STRIPE_WEBHOOK_SECRET!);
  } catch {
    return new Response("Invalid signature", { status: 400 });
  }
 
  // Stripe can send the same event more than once: skip events already handled
  const { data: seen } = await supabase
    .from("stripe_events")
    .select("id")
    .eq("id", event.id)
    .maybeSingle();
  if (seen) return new Response("Already handled", { status: 200 });
 
  switch (event.type) {
    case "checkout.session.completed":
    case "checkout.session.async_payment_succeeded":
      await fulfilCheckout(event.data.object.id); // must be safe to run twice for the same session
      break;
    case "customer.subscription.updated":
    case "customer.subscription.deleted":
      await syncSubscription(event.data.object.id); // re-read the subscription from Stripe, then save its status
      break;
  }
 
  await supabase.from("stripe_events").insert({ id: event.id, type: event.type });
  return new Response("ok", { status: 200 });
}

The important lines are the raw body and the signature check. Stripe signs every event, and verification fails if your framework parses or changes the body first. If the handler does slow work, Stripe recommends returning a 2xx response quickly and processing events from a queue.

Subscriptions

Subscriptions add a lifecycle on top. Stripe's subscription docs suggest granting access when you receive invoice.paid and the subscription status is active. Watch invoice.payment_failed to tell the customer their card needs updating, and remove access when the status becomes canceled or unpaid. customer.subscription.updated covers renewals and plan changes, and customer.subscription.deleted fires when a subscription ends.

Two details from the same docs are easy to miss. A paid invoice doesn't always mean the subscription is active, so retrieve the subscription and check its status before extending access. And if you offer trials, customer.subscription.trial_will_end arrives three days before a trial ends, which is the moment to check the customer has a payment method and remind them they are about to be charged.

Stripe also recommends that any production integration taking payments listens for refunds, disputes and early fraud warnings: charge.refunded, charge.dispute.created and radar.early_fraud_warning.created. Without them, you find out a customer disputed a charge only when you happen to check the Dashboard, and their account stays fully active in the meantime.

You don't need to build a billing page. Stripe's customer portal lets customers update their payment method, change or cancel their plan, and download invoices, and you can switch it on from the Dashboard without code.

Testing and fees

Test every path before you switch to live keys. Stripe's test card 4242 4242 4242 4242 succeeds, 4000 0000 0000 3220 requires 3D Secure authentication, and 4000 0000 0000 0002 is declined. Stripe's agreement prohibits testing live mode with real card details, so use these in a sandbox. The Stripe CLI can forward events to your machine with stripe listen --forward-to while you build.

On cost, Stripe's UK pricing for standard UK cards is 1.5% plus 20p per transaction, 2.5% plus 20p for cards from the EEA, and 3.15% plus 20p for international cards, with 2% more where currency conversion is needed. There are no setup or monthly fees. On a £20 monthly plan paid with a UK card, that is 50p a month.

The full walk-through is in adding Stripe to an AI-built app. For the tool-specific details, read Lovable Stripe payments, Bolt Stripe payments, v0 Stripe payments and Replit Stripe payments. Lovable also offers built-in payments on paid plans, and on its Free plan you can connect your own Stripe account instead.

Measure what users do

Analytics in a prototype is usually either nothing or everything: no tracking at all, or a tool that records every click and answers no question. For launch you need a handful of events that tell you whether people get value:

  • Signed up: an account was created.
  • Activated: they did the one job from your spec for the first time.
  • Started checkout: they tried to pay.
  • Paid: Stripe confirmed it, recorded from your webhook, not the browser.
  • Came back: they did the core job again on a different day.

That short list answers the questions that matter in the first month. Where do people drop off? Do the ones who activate also pay? Does anyone come back?

How you collect it matters in the UK. The ICO's current guidance on storage and access technologies includes an exception for analytics used only to collect statistical information to improve your service. To rely on it, you have to give people clear information about the purpose and a simple, free way to object. Anything connected to advertising, including ad measurement, still needs consent. If your analytics tool also feeds advertising, plan for a consent banner.

Read setting up MVP analytics for the setup itself.

UK GDPR basics

This isn't legal advice, and if you handle health, financial or children's data you need proper advice. For most early products, though, the basics are short.

Pay the data protection fee. The ICO says organisations, including sole traders, that use personal information need to pay a data protection fee unless they are exempt. Check whether you are on the ICO's site before launch.

Tell people what you do with their data. Under the right to be informed, you tell people why you are processing their personal data, how long you keep it, and who you share it with, at the time you collect it. The ICO asks for this to be concise, easy to find and written in plain language. A privacy page linked from your sign-up form is the usual way.

Collect less. Your one-page spec already lists the data you need and why. If a field isn't on that list, don't collect it. Every column of personal data is something to protect, export on request and eventually delete.

Know your suppliers. Your database host, email provider, payment processor and analytics tool all handle your users' data. List them in your privacy information and know which country each one stores data in.

Cookies. Cookies that are strictly necessary for the service a user asked for don't need consent, and the ICO is clear that no advertising purpose counts as strictly necessary. Analytics can rely on the statistical exception above if it meets the conditions.

The detail is in GDPR for startups in the UK.

Launch week

A good launch is boring. The work is in the week before.

  1. Run the launch checklist

    Go through every item in the app launch checklist on the production site, not the preview.

  2. Switch Stripe to live

    Swap in live keys, then update each webhook endpoint and copy its new signing secret. Live and sandbox endpoints have different secrets. Redeploy so the new values take effect.

  3. Pay for something yourself

    Make one real purchase with your own card on the live site, check the account upgrades, then refund it from the Stripe Dashboard.

  4. Turn on error alerts

    Make sure errors from the server and the browser reach somewhere you will see them on your phone, not only in a log nobody reads.

  5. Launch small

    Invite ten to twenty people you can talk to directly. Watch what they do, fix what breaks, then open the doors wider.

Stripe also publishes a go-live checklist covering keys, webhooks and account settings, and it is worth reading alongside mine.

Two more things to settle before launch week, because they take longer than you expect. First, email from your own domain. Sign-up confirmations, password resets and receipts sent from a builder's default address look like spam and are often treated that way. Set up a transactional email provider on your domain, connect it as your auth SMTP sender, and send yourself every email the app can send. Second, the domain itself. Make sure it is registered in your name, that you can log in to the registrar, and that the DNS changes have finished before you announce anything.

The step-by-step version is in launching an AI-built app, and the full list is the app launch checklist.

Your first 100 users

The first users rarely come from a launch post. They come from people you already know who have the problem, communities where those people already spend time, and direct conversations one at a time. That doesn't scale, which is the point. At this stage you want to watch each person use the product and hear why they did or didn't pay.

Three habits help more than any channel:

  • Talk to every early user. A fifteen-minute call tells you more than a month of analytics at this volume.
  • Fix what they hit, fast. Early users forgive bugs. They don't forgive being ignored.
  • Write down every reason someone didn't pay. After twenty or thirty conversations, the pattern tells you what to build next.

Read getting your first 100 users for where to find them and what to say.

Scaling, or starting again

Most MVPs don't have a scaling problem. They have a "nobody knows about it yet" problem. When growth does come, the first limits are usually slow queries on unindexed tables, a database on the smallest plan, and background work done inside a web request. All of those can be fixed in place. Scaling an MVP covers how to spot them early.

Sometimes, though, the prototype was the right way to learn and the wrong thing to grow. Signs it's time to rebuild rather than extend:

  • The data model doesn't fit the business you now have, such as a marketplace built for one kind of user.
  • Every new feature breaks an old one, and there are no tests to tell you which.
  • A team is about to take over, and they need a conventional codebase they can read without a guide.

My guide on whether to refactor or rebuild a vibe-coded app goes through that decision, and moving from no-code to code covers leaving a no-code tool. An MVP Build starts from £12,000 and takes 4 to 6 weeks, and your prototype becomes the brief.

Getting help with the launch

You can do everything in this guide yourself, and plenty of founders do. If you would rather hand it over, there are two ways I can help.

The Launch package takes a working prototype to production: code in your own GitHub, hosting in your name, Stripe set up with webhooks and subscriptions, analytics, the GDPR basics and the fixes in between. It is priced from the MVP Build and agreed in writing before I start.

If the prototype has deeper problems, such as data leaking between users, payments out of step with Stripe or a database that doesn't hold together, a Rescue Sprint fixes those first. It is a fixed price agreed after the free health check, and usually takes about a week.

If your app is in Lovable or Bolt, start with my guides to taking a Lovable app to production and taking a Bolt app to production, which cover each platform's hosting, export and limits.

Sources

The launch checklist for founders, as a PDF

About 40 checks across legal, payments, domain and email, analytics, backups and support.

You get the PDF now and two short follow-ups over the next week. Reply “stop” and the rest never arrive.

Questions founders ask

What is the difference between a prototype and a product?

A prototype proves an idea works for you. A product works for strangers: they can sign up without help, pay, trust you with their data, and come back tomorrow to find everything still there.

Do I need to move off Lovable or Bolt hosting to launch?

Usually not. Both can host a production app. Move when you have a specific reason, such as a team that needs a conventional setup, costs, or a feature the platform can't support.

How do I add Stripe payments to an AI-built app safely?

Use Stripe Checkout or Payment Links, and grant access from a verified webhook rather than the success page. Handle repeat events, failed renewals and cancellations, and test with Stripe's test cards before switching to live keys.

Can I launch a commercial app on Vercel's free plan?

No. Vercel's fair use guidelines restrict the Hobby plan to non-commercial personal use, and taking payments counts as commercial. A commercial app needs the Pro or Enterprise plan.

Ant

Product designer who builds MVPs, based in Nottingham. 10+ years designing digital products, and the only person at BlackFig. More about me