Quando usarlo
Il prodotto funziona in locale e serve il primo ambiente di produzione. I passi usano Vercel per l'hosting; va bene qualunque host Node.js in grado di chiamare l'endpoint del cron.
Regole da rispettare
SUPABASE_SERVICE_ROLE_KEY,STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRETeCRON_SECRETrestano solo lato server: mai con prefissoNEXT_PUBLIC_e mai con valori nel repository.supabase/seed.sqlcontiene dati demo: non eseguirlo mai in produzione.- Un pagamento è confermato solo dal webhook Stripe firmato.
Passi
- Database. Crea il progetto Supabase di produzione e applica le
migration in ordine:
supabase link --project-ref <ref>esupabase db push. - Auth. In Supabase, in Authentication → URL Configuration, imposta Site URL e redirect URL sul dominio di produzione.
- Hosting. Importa il repository in Vercel e copia tutte le variabili di
.env.example:NEXT_PUBLIC_APP_URLè il dominio pubblico, senza barra finale;CRON_SECRETè un valore casuale lungo, per esempio daopenssl rand -hex 32.
- Stripe. Crea un endpoint webhook verso
https://<dominio>/api/stripe/webhookcon gli eventicheckout.session.completed,checkout.session.async_payment_succeeded,checkout.session.expiredecharge.refunded. Copia il signing secret inSTRIPE_WEBHOOK_SECRETe rifai il deploy. Usa prima le chiavi di test e passa a quelle live solo dopo i controlli qui sotto. - Cron.
GET /api/crondeve girare ogni 5-15 minuti conAuthorization: Bearer $CRON_SECRET. Su Vercel aggiungi unvercel.json:
Vercel invia l'header in automatico quando{ "crons": [{ "path": "/api/cron", "schedule": "*/10 * * * *" }] }CRON_SECRETè impostato. Gli intervalli inferiori al giorno richiedono il piano Pro; in alternativa usapg_cronconpg_netsu Supabase. - Email. Verifica il dominio di invio su Resend e imposta
RESEND_API_KEYedEMAIL_FROM. Senza, le notifiche vengono solo registrate nei log. - Primo admin. Registrati da
/registere promuovi l'utente dall'SQL editor di Supabase:update public.profiles set role = 'admin' where id = '<uuid utente>';
Controlli dopo il deploy
curl -i https://<dominio>/api/cronsenza header risponde401.- Una prenotazione di prova a pagamento resta
pending_paymentfinché il webhook non la conferma, e Stripe mostra la consegna del webhook riuscita. - Annullando quella prenotazione il rimborso segue la policy del servizio.
Completato quando
- i comandi di verifica passano in locale;
- i tre controlli qui sopra passano sul dominio di produzione;
- nessun segreto compare nel repository o nei bundle client.
