When sign-in works in development and breaks after deploying, the code is usually fine. A setting still points at your local or preview environment.
Step 1: Fix the Site URL and Redirect URLs
- Supabase dashboard → Authentication → URL Configuration.
- Set Site URL to your production domain (e.g.
https://yourapp.com). The default ishttp://localhost:3000. - Under Redirect URLs, add every live address: your custom domain,
*.vercel.app/*.lovable.app, and any callback path such ashttps://yourapp.com/auth/callback. - Save, then test in incognito.
Symptoms that point here: confirmation or reset emails link to localhost, or login "succeeds" and then lands on a blank page or bounces back to the login page.
Step 2: Check the production env vars
- Make sure the host has the Supabase URL and anon/publishable key for the same project you use in development.
- Redeploy after changing them, because Vite bakes them in at build time.
- In DevTools → Network, find the auth request. If it goes to
undefined/auth/v1/..., the variables are missing.
Step 3: Signup emails never arrive
Supabase's built-in email sender is meant for testing and is heavily rate-limited. For a live app:
- Set up custom SMTP (any transactional email provider) under Project Settings → Auth → SMTP.
- Or, temporarily, turn off "Confirm email" while you test.
Step 4: Google / OAuth login fails
- In Google Cloud Console, add your production domain to Authorized JavaScript origins, and add Supabase's callback URL (shown on the Google provider page in Supabase) to Authorized redirect URIs.
- If the OAuth consent screen is still in Testing, only listed test users can sign in. Publish it.
Step 5: Endless spinner after login
If login works but the app hangs on "loading", check supabase.auth.onAuthStateChange. Awaiting another Supabase call inside that callback can deadlock the client. Keep the callback synchronous and defer any extra work:
supabase.auth.onAuthStateChange((event, session) => {
setSession(session);
setTimeout(() => loadProfile(session?.user.id), 0);
});Step 6: "Database error saving new user"
This comes from a trigger on auth.users (often a "create profile" function) that's failing. Check Logs → Postgres for the exact error. Common fixes: a missing column in profiles, or making the trigger function security definer.
Step 7: Test as a stranger
Use an incognito window and an email address you've never used before. Old cookies and sessions hide most of these bugs.
Run a free ReplayWatch scan. Paste your live URL and ReplayWatch checks it for page load, security headers, secrets exposed in your HTML/JS, Supabase/Firebase data that is readable without login, broken links and assets, SEO tags, and whether your signup page is reachable. It does not log in or run your signup flow. → https://replaywatch.com/#scan