AI-app werkt in de preview, maar niet na het deployen
De preview van je AI-builder regelde dingen die je eigen host niet weet: de omgevingsvariabelen, de toegestane adressen voor inloggen en CORS, en een regel die elke route naar je app stuurt. Zet de variabelen bij je host en bouw opnieuw, zet je domein in de redirect-lijst van je auth, en stel een rewrite naar index.html in. Faalt de build zelf, draai hem dan lokaal met dezelfde commando’s als je host.
Een app die in de preview werkt en na het deployen niet, is bijna nooit kapot. Hij mist iets wat de builder voor je regelde zonder het te zeggen. Hieronder de symptomen, waar ze vandaan komen, en per oorzaak hoe je hem vindt en oplost, in de volgorde waarin je ze het snelst uitsluit.
Herken je dit?
- Op je eigen domein zie je een witte pagina, terwijl in de preview alles werkt.
- In de console van je browser staat
supabaseUrl is requiredof een fout over een ontbrekende key. - Een bevestigingsmail of een link om je wachtwoord te herstellen opent
localhost:3000of het adres van de preview. - De homepage werkt, maar wie op
/dashboardververst of een link deelt, krijgt een 404. - In de console staat
blocked by CORS policyzodra de app een functie of API aanroept. - Je host meldt een mislukte build, met een fout die de preview nooit liet zien.
De preview regelde wat je host niet weet
Een AI-builder draait je app in zijn eigen omgeving. Daar staan je Supabase-URL en je key al klaar, staat het preview-adres al in de lijsten van toegestane adressen, en krijgt elke route vanzelf je app terug. De preview is vaak ook een ontwikkelserver, die meer door de vingers ziet dan een productiebuild.
Je host begint leeg. Hij kent geen variabelen, staat in geen enkele lijst, en zoekt bij /dashboard naar een bestand met die naam. Elk symptoom hierboven komt uit een van die verschillen.
Zo vind en los je het op, per oorzaak
1. Omgevingsvariabelen die de builder invulde
Vite zet variabelen die met VITE_ beginnen tijdens de build letterlijk in je JavaScript; Next.js doet hetzelfde met NEXT_PUBLIC_. Ze moeten dus bij je host staan voordat hij bouwt, en na elke wijziging bouw je opnieuw. Een .env-bestand dat in .gitignore staat, komt nooit bij je host aan.
Een Lovable-app met een Supabase-backend leest er drie: VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY en VITE_SUPABASE_PROJECT_ID. Andere builders gebruiken andere namen. Kijk in je eigen code welke het zijn.
grep -rhoE "import\.meta\.env\.[A-Z_]+|process\.env\.[A-Z_]+" src/ | sort -uControleer daarna of de waarden in de build terechtkomen.
npm run build
grep -o "https://[a-z0-9]*\.supabase\.co" dist/assets/*.js | sort -uGeheime keys, zoals die van OpenAI of Stripe, horen niet in deze lijst. Die zet je als secret bij de server of de functie die ze gebruikt, zonder voorvoegsel. Staat er toch een met VITE_ ervoor, lees dan eerst API-key gelekt.
2. Inloglinks die naar de preview of localhost wijzen
Supabase stuurt bevestigingsmails, magic links en wachtwoordlinks naar de Site URL, tenzij je app een ander adres meegeeft dat in de lijst met Redirect URLs staat. De Site URL staat standaard op http://localhost:3000. Beide vind je in het dashboard bij Authentication, onder URL Configuration.
Site URL:
https://www.jouwdomein.nl
Redirect URLs:
https://www.jouwdomein.nl/**
https://jouwdomein.nl/**
http://localhost:5173/**Zoek daarna in je code naar adressen die de builder er vast in zette.
grep -rn "lovable.app\|localhost:\|redirectTo" src/Staat er bij redirectTo een vast adres, vervang het dan door window.location.origin met het pad erachter. Log je in met Google of een andere provider via je eigen Supabase-project, dan blijft de callback bij die provider het adres van Supabase. Daar hoeft je domein niet bij.
3. Een 404 bij verversen of een gedeelde link
Een app uit een Vite-builder is één pagina, index.html, en de router in de browser bepaalt wat je ziet. Klik je in de app naar /dashboard, dan gaat het goed. Ververs je daar, dan vraagt de browser je host om een bestand dat /dashboard heet, en dat bestaat niet. De oplossing is een rewrite die elk onbekend pad naar index.html stuurt, met status 200.
# Vercel: vercel.json in de hoofdmap van je project
{ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] }
# Netlify: public/_redirects
/* /index.html 200
# Apache: .htaccess naast index.html
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]Lovable-projecten die vanaf 13 mei 2026 zijn aangemaakt, gebruiken TanStack Start met een eigen server. Daar hoort deze regel niet bij: zo’n app moet op een host die een server draait. Hoe je ziet welke je hebt, staat in Lovable-app exporteren en zelf hosten.
4. CORS-fouten bij functies en API’s
CORS is de afspraak waarmee een server de browser vertelt welke websites hem mogen aanroepen. In de preview kwam het verzoek van een adres dat al was toegestaan; jouw domein staat er nog niet bij. Een Supabase Edge Function moet het voorverzoek van de browser (OPTIONS) zelf beantwoorden, en elk antwoord moet de headers meekrijgen.
const corsHeaders = {
'Access-Control-Allow-Origin': 'https://www.jouwdomein.nl',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
}
Deno.serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}
// ... wat je functie doet
return new Response(JSON.stringify({ ok: true }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
})
})Een CORS-melding is vaak een andere fout in vermomming. Een functie die niet gedeployd is, of die crasht omdat een secret ontbreekt, antwoordt zonder deze headers, en dan meldt de browser CORS. Kijk daarom eerst in de logs van de functie. Werk je met de GitHub-koppeling van Lovable: gewijzigde Edge Functions die via GitHub binnenkomen, deployt Lovable niet vanzelf.
5. Een build die faalt bij je host
Je host draait npm run build, controleert soms de types, en werkt meestal op Linux. Daar zijn Header.tsx en header.tsx twee verschillende bestanden, dus een import met de verkeerde hoofdletter werkt op je Mac en faalt op de host. Draai lokaal precies wat je host draait.
npm ci # installeert exact wat in package-lock.json staat
npm run build # dezelfde build als je host
npm run preview # toont de build zoals hij live komtZet ook de Node-versie vast in package.json, met een regel als "engines": { "node": "22.x" }, zodat je host dezelfde versie gebruikt als jij.
Waar het daarna nog misgaat
- Een variabele aanpassen zonder opnieuw te bouwen. De oude waarde staat nog in de JavaScript die live staat. Start bij je host een nieuwe deploy; verversen in de browser doet niets.
- De redirect-lijst te ruim maken. Met een patroon dat elk domein toestaat, werkt inloggen overal, en mag een inloglink ook naar een adres dat niet van jou is. Noem elk adres dat je gebruikt, en zet
**alleen achter je eigen domein. - De 404 wegwerken met een foutpagina. Sommige hosts laten je
index.htmlals 404-pagina instellen. Bezoekers zien dan je app, maar je host stuurt status 404 mee, en zoekmachines slaan die pagina’s over. Waarom dat voor Google telt, staat bij AI-website niet gevonden in Google. - De host laten bouwen wat de builder schrijft. Met de GitHub-koppeling van Lovable of Bolt wordt elke wijziging in de builder een commit. Bouwt je host die branch automatisch, dan gaat elke prompt meteen live. Laat de host een aparte branch bouwen, en zet daar alleen op wat je getest hebt.
Wanneer je hulp nodig hebt
Werkt de app na deze stappen nog steeds niet, of draait hij wel maar weet je niet of hij dichtzit, laat dan iemand meekijken. Bij je AI-app laten afmaken zetten we hem live op je eigen domein en hosting, samen met de onderdelen die nog ontbreken. Wil je eerst weten wat er openstaat voordat er echte gebruikers in komen, begin dan met de securitycheck.
Kies je nieuwe hosting, neem dan meteen een Europese regio: wat dat vraagt, staat bij je app naar Europese hosting en in wat AI-tools niet voor je regelen. Je database test je met Supabase RLS controleren; wat RLS is, lees je in Row Level Security uitgelegd. De problemen die we in AI-sites verder vaak zien, staan in je website is met AI gebouwd, en alle gidsen over apps op AI-apps afmaken en beveiligen.
Veelgestelde vragen
Waarom werkt inloggen wel op het adres van de builder en niet op mijn domein?
De build is gelukt, maar ik zie een witte pagina.
Werkt dit ook voor een app uit Cursor of Claude Code?
Kan de builder dit niet zelf oplossen?
Verder lezen
Een app die je met Lovable, Bolt, v0, Cursor of Claude bouwde: dichtzetten, afmaken en online houden.
- Securitycheck voor je AI-app
- Een vaste check van je app uit Lovable, Bolt, v0, Cursor of Claude Code: databaserechten, keys, inloggen, webhooks en de AVG-basis. Met een rapport en de fixes.
- AI-app laten afmaken
- Je prototype uit Lovable, Bolt, v0, Cursor of Claude Code werkt, maar is nog niet klaar voor klanten. Wij bouwen de rest: betalingen, rollen, e-mail, beheer, hosting en onderhoud.
- API-key gelekt
- Een key van OpenAI, Anthropic, Supabase of Stripe in je frontend of je git-geschiedenis: intrekken, vervangen, limiet erop.
- Supabase RLS controleren
- Je database testen zoals een buitenstaander dat doet: met de publieke key, als tweede gebruiker en in je opslag. Met de SQL om te ruime policies te vinden.
- Lovable-app zelf hosten
- Van Lovable naar je eigen GitHub, domein en hosting, met of zonder eigen Supabase-project. Wat er meekomt, wat achterblijft, en waar Bolt en v0 anders werken.
Wij zetten hem live op je eigen domein
De kennismaking is gratis. We reageren binnen één werkdag.




