FixLoop

Lovable login works in preview, breaks in production

Guide · October 14, 2026

You can sign in on the Lovable preview. You publish (or put a custom domain in front) and login loops, dumps you on localhost:3000, or comes back with no session. The React is the same. The host is not.

Supabase Auth only sends the browser to URLs it already trusts. Preview was on that list. Production was not.

Sources: Redirect URLs, redirectTo troubleshooting, Sign in with Google (the callback URL pattern is the same for other providers), and Lovable's Supabase integration (auth settings live in the Supabase dashboard on a connected project).

What it looks like

Open a private window on the live origin. Preview cookies will lie to you.

Three lists, not one

People paste the production URL into one box and call it done. There are three:

  1. Supabase Site URL (Authentication → URL Configuration). Default redirect when code does not pass redirectTo. Magic links and password resets use it. Default on a new project is http://localhost:3000.
  2. Supabase Redirect URLs (same page, allowlist). Every redirectTo must match. If it does not, Auth ignores it and uses Site URL, which is how you "set production" and still bounce to localhost. Documented in the redirectTo FAQ.
  3. OAuth provider Authorized redirect URI (Google Cloud, GitHub, etc.). This is not your app. It is Supabase's callback: https://YOUR_PROJECT.supabase.co/auth/v1/callback, copied from Authentication → Providers. Publishing the Lovable app does not change this URL. Getting it wrong is redirect_uri_mismatch at the provider, which looks like a Lovable bug.

On a connected Supabase project, those first two live in the Supabase dashboard. Lovable's docs are blunt: social providers and auth URL settings are not configured from the project chat. (Lovable Cloud, the built-in backend, is the other setup. This guide is the connected-project case.)

The fix

1. Site URL = the live origin

Authentication → URL Configuration → Site URL:

https://myapp.com

Or https://your-app.lovable.app if that is the published host. Include https://. No path unless you really serve the app under one. Save.

Leave preview out of Site URL. Site URL is the default for emails. Preview can stay on the Redirect URLs list.

2. Redirect URLs include production, preview, and the callback path

Same page, Redirect URLs. Add the origins you actually use. Wildcards are documented; ** matches across /:

https://myapp.com/**
https://myapp.com/auth/callback
https://*.lovable.app/**
http://localhost:5173/**
http://localhost:3000/**

Use the path your client passes as redirectTo. If the code sends https://myapp.com/auth/callback, that exact URL (or a wildcard that covers it) must be on the list. A trailing-slash mismatch is enough to fall back to Site URL.

The docs recommend an exact production path, and ** for preview hosts. That split is the right one.

3. Provider callback = the supabase.co URL

Google Cloud Console (or GitHub → Developer settings → OAuth app):

https://YOUR_PROJECT.supabase.co/auth/v1/callback

Do not put https://myapp.com/auth/callback in Google's redirect URI list. Google returns to Supabase. Supabase then returns to your app using Site URL / redirectTo.

4. redirectTo in the app

Hardcoding the preview host is how production "randomly" returns to preview. Use the current origin, or a production env var:

const redirectTo = `${window.location.origin}/auth/callback`;

const { error } = await supabase.auth.signInWithOAuth({
  provider: "google",
  options: { redirectTo },
});

Same idea for resetPasswordForEmail and signInWithOtp. Whatever string you pass must be on Redirect URLs. No redirectTo means Site URL, which is why setting Site URL to production also fixes magic links.

If you customized auth email templates, {{ .SiteURL }} always points at Site URL. Use {{ .RedirectTo }} when the link should follow the redirectTo you passed. That is in the same redirect-URLs guide.

Quick checklist

Questions

Why does Lovable login work in preview but fail after publish?

Preview and production are different origins. Auth only returns to allowlisted URLs. If Site URL and Redirect URLs still name the preview host or localhost, production sign-in is rejected or sent to the wrong place.

What is the difference between Site URL and Redirect URLs?

Site URL is the default when you omit redirectTo (emails, some OAuth fallbacks). Redirect URLs is the allowlist for every redirectTo. Production needs both. A redirectTo that is not on the list is ignored.

Where does the Google or GitHub callback URL go?

In the provider console, Authorized redirect URI is the Supabase callback https://YOUR_PROJECT.supabase.co/auth/v1/callback. Your app URL goes in Supabase Site URL / Redirect URLs, and as a JavaScript origin at the provider. Publishing does not change the supabase.co callback.

I set Site URL. Why do I still land on localhost?

redirectTo is missing from Redirect URLs, so Auth falls back, or the client still hardcodes localhost/preview. Add the exact production callback and pass window.location.origin.

Do I configure this in Lovable or in Supabase?

Connected project: Supabase Dashboard → Authentication → URL Configuration, plus the provider console. Lovable Cloud (built-in backend) is configured in Lovable. The two backends are not interchangeable in one click.

If the session exists and Save still no-ops, that is RLS, not redirects: saved but nothing saved. If production checkout 401s at the webhook, see Stripe webhook 401.

Login dead on the live domain? That is an auth fix. $149, you test the PR before you pay. No fix, no pay.

Get this fixed for $149