Lovable Preview vs Production: 9 Fixes for Founders

  • Wednesday, October 14, 2026

Your Lovable preview works but production breaks. Diagnose and fix the nine most common causes, from missed republishes to Stripe live-mode keys.

A Lovable app that works in preview but breaks in production is almost never a code problem. The preview runs your newest changes against development settings. The live site runs a published snapshot against whatever you configured for your production domain. Nine configuration gaps cause most of these failures, and you can check all of them in an afternoon.

This guide is for founders who have published a Lovable, Bolt or Replit app and found that sign-ups, payments or whole pages stop working on the real URL. It covers how to read the failure, the nine fixes in the order we apply them, and how to tell when the problem is deeper than configuration. If you have not launched yet, start with our pre-launch checklist for AI-built apps and come back here when something breaks.

Key takeaways

  • The preview always shows your newest work. The live site shows the last snapshot you published, so an unpublished change looks exactly like a production bug.
  • Front-end configuration is compiled into the build, not read at runtime. Changing a value means rebuilding and republishing.
  • Most broken sign-ups come down to one setting: the Supabase Site URL still pointing at localhost or the old preview address.
  • Stripe test mode and live mode share nothing. Keys, products, prices and webhook signing secrets all have to be swapped together.
  • A failure that survives all nine fixes is usually a data-access or logic problem rather than a deployment problem.

Why does a Lovable app work in preview but break in production?

Because the preview and the live site are two different deployments with two different sets of configuration. The preview reloads your current code with your development values attached. Production serves a published snapshot with whatever keys, domains and database settings exist in the live environment.

Lovable's own documentation is explicit about the snapshot: each publish deploys a snapshot of your project, only the current version is deployed, and later changes are not pushed live automatically. Accepting a draft is not publishing either (Lovable's publishing documentation).

What it depends on Preview Published site
Code version Your latest accepted changes The last snapshot you published
Address it runs on A preview URL Your lovable.app subdomain or custom domain
Front-end config Compiled into the preview build Compiled into the published build
Server-side secrets Development values Secrets set on the production project
Payment provider Test mode Live mode, once you switch it

Read the failure before you change anything

Open the live site in a private browser window, open developer tools, and watch the Console and Network tabs while you reproduce the problem. The first red line usually names the fix. Guessing and re-prompting the AI tool burns credits and rewrites code that was fine.

What you see on the live site Where to look first
Blank white page A console error on load, usually a missing front-end variable
An older version of the app Unpublished changes, or a cached build (fixes 1 and 3)
Login works, then bounces back Supabase Site URL and Redirect URLs (fix 7)
401 or 403 on data requests Keys for the wrong project, or missing policies (fix 8)
Checkout opens but fails Stripe still in test mode (fix 6)
Confirmation emails stop arriving The built-in email rate limit (fix 9)

Fixes 1 to 3: is the live site running what you think it is?

These three checks take five minutes and rule out roughly half of all reports. Do them before you touch any settings.

1. Republish, then check again

The most common cause is also the simplest: the change exists in your project but was never deployed. Lovable puts a small dot on the Publish button when the project holds changes newer than the live version. Open the publish dialog and click Publish changes.

This catches people out because accepting a draft feels like shipping. It is not. Accepted edits join your unpublished changes, and visitors see them only after the next publish.

2. Confirm the custom domain is serving the published app

Compare two addresses side by side: the lovable.app URL and your custom domain. If the lovable.app address works and the domain does not, the app is fine and the problem is domain setup.

A domain only starts serving your site after the project has been published, and while the connection is still being set up Lovable keeps serving the lovable.app address instead. A domain you added this morning may still be pointing at a parked page or your old marketing site.

3. Rule out a stale build in your browser

Your browser may be holding an older copy of the app. Before you debug anything, do a hard reload, then load the site in a private window, then on your phone. If the private window shows the new version, there was never a production bug.

The reverse is just as useful. If every device shows the old version, the publish did not happen or did not finish.

Fixes 4 to 6: keys, secrets and environment variables

Configuration values live in two places that behave very differently: secrets held on the server, and variables compiled into the browser bundle. Mixing them up breaks the live app and, worse, can expose a key.

4. Set production secrets as well as development ones

Server-side code reads secrets from the environment it runs in, and local and production environments load them separately. A key that works on your machine is simply absent in production until you add it there, which is why a function that worked all week returns a 500 the moment it runs live.

Set production secrets in the Supabase dashboard under Edge Function Secrets, or from the command line:

supabase secrets list
supabase secrets set STRIPE_SECRET_KEY=sk_live_...

Deployed functions pick up a new secret immediately, so there is nothing to redeploy. Secret names cannot start with SUPABASE_, which is reserved for the values the platform injects. If a function returns a 500 with no useful message, read its logs and look for an undefined environment variable before you assume the code is wrong.

5. Remember that front-end variables are frozen into the build

Lovable apps are built with Vite, which handles browser-side configuration in a way that surprises most founders. Only variables prefixed with VITE_ are exposed to client code, and their values are substituted into the code at build time rather than read when the app runs (Vite's environment variable guide).

Two things follow. First, editing a value does nothing to the live site until you rebuild and publish, so "I changed the key and it still fails" is expected behaviour rather than a bug. Second, anything in a VITE_ variable ships inside the JavaScript every visitor downloads.

That second point decides which keys are allowed there. A Supabase publishable key belongs in the bundle and is designed to be public. A Stripe secret key, a service-role key or a model provider key does not, and putting one there to make a feature work hands it to every visitor. If that has already happened, rotate the key before you do anything else.

6. Move Stripe into live mode completely

Switching Stripe to live mode is four changes, not one, and missing any of them produces a checkout that looks right and fails. Stripe's documentation is clear that each mode has its own API keys and that objects in one mode are not accessible from the other, so a sandbox product cannot be part of a live-mode payment. Webhook signing secrets are separate again, with one per endpoint (Stripe's API keys reference).

The swap therefore covers the publishable key, the secret key, the product and price IDs, and a live webhook endpoint with its own signing secret. A "no such price" error on the live site almost always means test-mode price IDs are still hard-coded. Signature verification failures almost always mean the live endpoint's secret was never copied across.

Our walkthrough of adding payments and subscription billing to a SaaS MVP covers the webhook handling itself, including retries and duplicate events.

Fixes 7 to 9: auth, data and the plan you are on

The last three fixes are where founders lose the most time, because the app looks fine to you and only new users hit the problem.

7. Point Supabase Auth at your production domain

One setting breaks sign-up on nearly every newly launched app. Supabase's Site URL is the default redirect used when your code does not pass a redirectTo value, it starts out as http://localhost:3000, and Supabase's guidance is to change it to your production URL because it governs email confirmations and password resets (Supabase's redirect URL configuration).

Leave it alone and your confirmation emails send users to a page that exists only on your laptop. The fix is two steps: set Site URL to your live domain, then add every address the app is served from, the lovable.app subdomain included, to the Redirect URLs allow list. Social logins fail the same way when the production callback URL was never added at the provider.

8. Check that schema changes and policies reached the production database

If your preview and your live site talk to different Supabase projects, anything you added in one is missing from the other. A 404 on a table name, or an error about a column that does not exist, points straight at a migration that was never applied to production.

A quieter version of the same problem is row level security, the database rule that decides which rows each request may read. A query that returned your rows while you were the only user returns an empty array for a new account when no select policy exists, so the page renders with no error and no data. Our guide to finding and fixing RLS gaps in Supabase apps covers the policies and the tests for them.

9. Replace the built-in email service and check your plan

Two platform limits bite within days of launch. Supabase's production checklist states that the default rate limit on endpoints that send auth emails was updated to two emails per hour, changeable only with your own SMTP credentials, and that projects on the Free plan may be paused after a seven-day period of low activity (Supabase's production checklist).

The first limit explains the strangest symptom on this list: your first two sign-ups get a confirmation email and everyone after them gets nothing, with no error anywhere. Connect your own email provider and that default rises to 30 new users per hour. The second explains an app that worked last month and returns connection errors today. Our guide to getting transactional email to actually arrive covers provider setup and the DNS records behind it.

Common mistakes when debugging a live Lovable app

  • Re-prompting without the error. Paste the exact console message into the chat. Asking the tool to "fix production" makes it rewrite code that was never broken.
  • Changing several settings at once. Change one, republish, retest. Otherwise you cannot tell which change fixed it or what else you broke along the way.
  • Testing only in your own browser. Your session, your cache and your admin account all hide problems a stranger hits immediately.
  • Sharing one database between preview and production. It removes this whole class of bug and replaces it with a worse one, where a bad migration takes the live app down.
  • Treating an exposed key as fixed once it has been moved. A key that has ever sat in a browser bundle or a chat log is public. Rotate it.

Frequently asked questions

Why does my Lovable app show a blank page after publishing?

A blank page means the JavaScript failed before it could render anything, and the browser console names the cause. The usual culprits are a front-end variable that exists in the preview build but not the published one, or a build that failed and left the previous version in place. A blank page with no console error at all is a different problem, usually the domain not yet serving the app.

Do I need to republish after changing an environment variable?

For anything the browser reads, yes. Vite substitutes those values into the bundle at build time, so the live site keeps using the old value until you publish a new build. Server-side secrets, including Supabase Edge Function secrets, are read at runtime and take effect without a republish.

Why do my confirmation emails link to localhost?

Because the Supabase Site URL is still set to its default of http://localhost:3000. Change it to your production domain and add that domain to the Redirect URLs list. Emails already sent keep the old link, so test with a fresh sign-up rather than an old message.

My app worked for weeks and is down now. What changed?

Usually nothing you did. The common causes are a Free-plan database paused for inactivity, an expired API key or certificate, a payment method that failed on a provider account, or a usage limit reached after a traffic spike. Check your provider dashboards before you look at the code.

Getting your app working on the live domain

Work the list in order. Republish and clear the cache first, confirm the domain is actually serving the published app, then move through secrets, Stripe mode, the Supabase Site URL and the production schema. Most failures are gone by fix 7, and the few that survive are genuine application bugs worth fixing properly rather than prompting around.

If you would rather hand it to engineers who have walked this path before, AlgoSmiths works on fixed-price projects with a working demo every week. You can see how a stuck AI-built app gets to launch on our home page.

Posted In:
Software & SaaS Solutions

Add Comment Your email address will not be published