Aggiungi notifiche e-mail al tuo sito di prenotazione con IA

Invia e-mail di conferma prenotazione e avvisi al titolare usando Supabase, Resend ed Edge Functions.

Roadmap e risorse

Nuovo qui? Parti prima da qui

Questa guida aggiorna il progetto del sito di prenotazione con IA con notifiche e-mail automatiche. Se non hai ancora costruito il sito di prenotazione, parti prima dalla guida principale.

Crea un sito di prenotazione con l'IA

Apri la guida principale

MAIN GUIDE

https://profitstudio.app/video/build-booking-website-ai

Configurare Resend per le e-mail di prenotazione

Crea e configura il tuo account Resend

Apri Resend

https://resend.com/

Crea un account Resend Genera una chiave API di Resend Copia e salva la chiave API in modo sicuro

IMPORTANTE

Mantieni privata la chiave API di Resend. Non aggiungerla mai al codice frontend e non condividerla pubblicamente.

Aggiungi e verifica il tuo dominio di invio

Aggiungi il dominio del tuo sito di prenotazione Seleziona la regione più vicina Copia i record DNS da Resend Aggiungi i record presso il tuo provider di dominio Torna su Resend e conferma che il dominio è verificato

La verifica DNS può richiedere qualche minuto o più, a seconda del tuo provider di dominio.

Creare la funzione e-mail di prenotazione

Crea la Edge Function per le e-mail di prenotazione

Apri Supabase

https://supabase.com/?utm_source=partner&utm_medium=social&utm_campaign=supasquad&dub_id=faVfKdcLWvKCbYNp

Apri il tuo progetto Supabase Apri Edge Functions Crea una nuova funzione con l'editor del browser Assegna alla funzione il nome `send-booking-email` Rimuovi il codice iniziale predefinito

Personalizza e aggiungi il codice della funzione

Inserisci l'e-mail del proprietario Inserisci il dominio Resend verificato Inserisci il nome dell'attività mittente Personalizza i modelli e-mail se necessario Copia e incolla il codice della funzione generato

Funzione e-mail di prenotazione

import { serve } from "https://deno.land/std/http/server.ts"; serve(async (req) => { try { const body = await req.json(); const record = body.record || {}; const resendKey = Deno.env.get("RESEND_API_KEY"); const supabaseUrl = Deno.env.get("SUPABASE_URL"); const supabaseServiceRoleKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"); if (!resendKey) { return new Response( JSON.stringify({ error: "Missing RESEND_API_KEY secret" }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } const ownerEmail = "YOUR_OWNER_EMAIL"; const customerEmail = record.email || ""; const customerName = record.full_name || record.name || "Customer"; const phone = record.phone || ""; const appointmentDate = record.appointment_date || record.date || ""; const startTime = record.start_time || record.time || ""; const endTime = record.end_time || ""; const notes = record.notes || ""; const status = record.status || "New"; let serviceName = record.service_name || record.service || record.service_title || ""; // If the appointment only has service_id, fetch the service name from the services table if (!serviceName && record.service_id && supabaseUrl && supabaseServiceRoleKey) { try { const serviceId = encodeURIComponent(record.service_id); const serviceResponse = await fetch( `${supabaseUrl}/rest/v1/services?id=eq.${serviceId}&select=name`, { method: "GET", headers: { apikey: supabaseServiceRoleKey, Authorization: `Bearer ${supabaseServiceRoleKey}`, "Content-Type": "application/json", }, } ); const serviceData = await serviceResponse.json(); if (Array.isArray(serviceData) && serviceData.length > 0) { serviceName = serviceData[0].name || ""; } } catch (_serviceError) { serviceName = ""; } } if (!serviceName) { serviceName = "Appointment"; } // 1) Email to business owner const ownerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "Bookings <bookings@YOUR_DOMAIN_NAME>", to: [ownerEmail], subject: "OWNER_NOTIFICATION_SUBJECT", html: ` <h2>OWNER_NOTIFICATION_HEADING</h2> <p>OWNER_NOTIFICATION_INTRO</p> <p><b>Customer Name:</b> ${customerName}</p> <p><b>Email:</b> ${customerEmail}</p> <p><b>Phone:</b> ${phone}</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p><b>Notes:</b> ${notes}</p> <p><b>Status:</b> ${status}</p> `, }), }); const ownerData = await ownerResponse.json(); // 2) Email to customer let customerData = null; if (customerEmail) { const customerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "YOUR_BUSINESS_NAME <bookings@YOUR_DOMAIN_NAME>", to: [customerEmail], subject: "CUSTOMER_CONFIRMATION_SUBJECT", html: ` <h2>CUSTOMER_CONFIRMATION_HEADING</h2> <p>Hi ${customerName},</p> <p>CUSTOMER_CONFIRMATION_INTRO</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p>If you need to make any changes, please contact us before your appointment.</p> <p>CUSTOMER_CONFIRMATION_CLOSING</p> `, }), }); customerData = await customerResponse.json(); } return new Response( JSON.stringify({ success: true, ownerEmailSent: ownerData, customerEmailSent: customerData, }), { headers: { "Content-Type": "application/json" }, } ); } catch (error) { return new Response( JSON.stringify({ success: false, error: String(error), }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } });

E-mail del titolare

owner@example.com

Dominio verificato in Resend

yourdomain.com

Nome del business mittente

Clinica Dentistica Bright

Oggetto dell'e-mail al titolare

Intestazione dell'e-mail al titolare

Testo di introduzione dell'e-mail al titolare

Oggetto dell'e-mail al cliente

Intestazione dell'e-mail al cliente

Testo di introduzione dell'e-mail al cliente

Testo di chiusura dell'e-mail al cliente

Distribuisci e configura la funzione

Distribuisci la funzione Apri le impostazioni della funzione Disattiva `Verify JWT With Legacy Secret` Salva le modifiche Copia e conserva l'URL dell'endpoint della funzione per configurare il webhook

IMPORTANTE

Disattiva “Verify JWT With Legacy Secret” in modo che il Database Webhook possa richiamare la funzione.

Aggiungere la API key di Resend a Supabase

Aggiungi la chiave API di Resend come secret su Supabase

Apri Edge Function Secrets Crea un nuovo secret Imposta il nome su `RESEND_API_KEY` Incolla la chiave API di Resend Salva il secret

IMPORTANTE

Usa esattamente il nome del secret `RESEND_API_KEY`. Qualsiasi errore di battitura impedirà alla funzione di accedere a Resend.

Collegare le e-mail alle nuove prenotazioni

Crea il webhook per le e-mail di prenotazione

Attiva la funzione e-mail di prenotazione ogni volta che viene aggiunto un nuovo appuntamento.

Integrations Database Webhooks

Apri Database Webhooks Abilita Database Webhooks Crea un nuovo webhook Chiamalo `send-booking-email-webhook` Seleziona la tabella `public.appointments` Scegli `Insert` come evento Mantieni `HTTP Request` come tipo Usa `POST` come metodo della richiesta Incolla l'URL dell'endpoint della Edge Function Crea il webhook

Testare il sistema di e-mail di prenotazione

Testa l'intero flusso di e-mail di prenotazione

Testa l'intero flusso di prenotazione e conferma che entrambe le e-mail vengano recapitate correttamente.

Apri il sito di prenotazione online Invia un appuntamento di prova Conferma che la prenotazione sia salvata su Supabase Controlla l'e-mail di conferma al cliente Controlla l'e-mail di notifica al proprietario Verifica che i dettagli della prenotazione siano corretti in entrambe le e-mail Conferma che la prenotazione compaia nella dashboard di amministrazione