Wann du es brauchst
Das Produkt läuft lokal und braucht seine erste Produktionsumgebung. Die Schritte gehen von Vercel als Hosting aus; jeder Node.js-Host funktioniert, der den Cron-Endpunkt aufrufen kann.
Regeln, die gelten bleiben
SUPABASE_SERVICE_ROLE_KEY,STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRETundCRON_SECRETbleiben serverseitig: nie mitNEXT_PUBLIC_-Präfix und nie mit Werten im Repository.supabase/seed.sqlenthält Demodaten: niemals in Produktion ausführen.- Eine Zahlung wird nur durch den signierten Stripe-Webhook bestätigt.
Schritte
- Datenbank. Lege das Supabase-Produktionsprojekt an und wende die
Migrationen der Reihe nach an:
supabase link --project-ref <ref>undsupabase db push. - Auth. Setze in Supabase unter Authentication → URL Configuration die Site URL und die Redirect-URLs auf die Produktionsdomain.
- Hosting. Importiere das Repository in Vercel und übernimm alle
Variablen aus
.env.example:NEXT_PUBLIC_APP_URList die öffentliche Domain, ohne abschließenden Schrägstrich;CRON_SECRETist ein langer Zufallswert, zum Beispiel ausopenssl rand -hex 32.
- Stripe. Lege einen Webhook-Endpunkt auf
https://<domain>/api/stripe/webhookmit den Eventscheckout.session.completed,checkout.session.async_payment_succeeded,checkout.session.expiredundcharge.refundedan. Kopiere das Signing Secret nachSTRIPE_WEBHOOK_SECRETund deploye erneut. Nutze zuerst Testschlüssel und wechsle erst nach den Prüfungen unten zu Live-Schlüsseln. - Cron.
GET /api/cronmuss alle 5–15 Minuten mitAuthorization: Bearer $CRON_SECRETlaufen. Auf Vercel ergänzt du einevercel.json:
Vercel sendet den Header automatisch, wenn{ "crons": [{ "path": "/api/cron", "schedule": "*/10 * * * *" }] }CRON_SECRETgesetzt ist. Intervalle unter einem Tag erfordern den Pro-Plan; alternativpg_cronmitpg_netauf Supabase. - E-Mail. Verifiziere die Absenderdomain bei Resend und setze
RESEND_API_KEYundEMAIL_FROM. Ohne sie werden Benachrichtigungen nur protokolliert. - Erster Admin. Registriere dich unter
/registerund befördere den Nutzer im SQL-Editor von Supabase:update public.profiles set role = 'admin' where id = '<user uuid>';
Prüfungen nach dem Deploy
curl -i https://<domain>/api/cronohne Header antwortet mit401.- Eine bezahlte Testbuchung bleibt
pending_payment, bis der Webhook sie bestätigt, und Stripe zeigt die Webhook-Zustellung als erfolgreich an. - Wird diese Buchung storniert, folgt die Erstattung der Policy des Service.
Fertig, wenn
- die Prüfbefehle lokal erfolgreich laufen;
- die drei Prüfungen oben auf der Produktionsdomain bestehen;
- kein Secret im Repository oder in Client-Bundles auftaucht.
