Home / Progetti / Piattaforma di prenotazione

Sostituire Typeform, Calendly e Zapier con un'unica piattaforma di prenotazione

Un unico sistema di proprietà ha sostituito tre abbonamenti SaaS ricorrenti — Typeform, Calendly e Zapier — spostando l'intero flusso di prenotazione dentro Google Workspace, personalizzabile a ogni passaggio e non dipendente da alcun fornitore esterno.

Stato In produzione · v3.2
Scala~4.000 prenotazioni / mese
Tecnologie principaliGoogle Calendar API · Google Sheets API · Google Apps Script · TypeScript
01

Panoramica

Un sistema di pianificazione che consente a un team di servizi distribuito di accettare prenotazioni su molti professionisti senza mai prenotare due volte, gestire male un fuso orario o duplicare un appuntamento su una ripetizione, con Google Calendar come unica fonte di verità.

Cosa è stato costruito

Una piattaforma di prenotazione posata direttamente su Google Workspace. I clienti scelgono uno slot dalla disponibilità calcolata; la piattaforma riserva, verifica e conferma l'appuntamento come un'unica transazione idempotente, scrivendo l'evento sul Google Calendar del professionista e notificando entrambe le parti. Non esiste un database di riferimento separato: il calendario in cui il team già vive resta autoritativo.

A chi è rivolto

Un'attività di servizi che gestisce diversi professionisti, ciascuno con i propri orari di lavoro, margini e periodi di assenza, che accetta prenotazioni da un modulo web, dall'email e dall'occasionale telefonata inserita a posteriori.

Contesto aziendale

Il processo manuale che ha sostituito perdeva all'incirca uno slot a settimana per doppie prenotazioni e slittamenti di fuso orario: pochi in numero, costosi in fiducia. Il compito della piattaforma era rendere il calendario autoritativo e la prenotazione sicura, senza aggiungere un secondo sistema che sarebbe finito fuori sincrono.

02

Architettura

Un coordinatore sottile e senza stato davanti a Google Calendar. Una prenotazione è una transazione breve e idempotente — riserva, verifica, conferma — instradata attraverso una coda per singolo professionista, così che la corsa che causa la doppia prenotazione non possa verificarsi.

Clientmodulo web / intake email
EdgeCloud Function — validazione + normalizzazione TZ
CodaCloud Tasks — FIFO per singolo professionista
↓ una prenotazione alla volta, per professionista ↓
Coordinatoreriserva → verifica → conferma
RegistroFirestore — chiavi di idempotenza (TTL)
Fonte di veritàGoogle Calendar — freebusy + eventi

Perché una coda per professionista

La doppia prenotazione è una corsa tra scrittori concorrenti per una singola risorsa. Anziché ricorrere a lock distribuiti, ogni richiesta per un dato professionista passa attraverso un'unica coda FIFO a consumatore singolo — una primitiva noiosa e debuggabile che rende la corsa impossibile invece che semplicemente recuperabile. La concorrenza tra professionisti resta alta; all'interno di un singolo professionista scende a uno.

03

Componenti

La piattaforma è costruita da nove componenti. Ognuno è documentato come una propria sezione ingegneristica — perché esiste, la sua architettura, i vincoli e i casi limite che gestisce, i compromessi presi e l'implementazione finale. Espandi uno qualsiasi per leggerlo.

C1Flusso di prenotazione a più passaggirivolto al client
Perché esiste
Trasforma il "trova un orario" in una sequenza guidata e riprendibile — servizio → professionista → data → slot → dettagli → conferma — che non presenta mai uno slot che non può onorare.
Architettura
Un client senza stato pilotato dal motore di disponibilità; ogni passaggio ri-valida rispetto al free/busy in tempo reale, così che uno slot che si riempie a metà flusso venga intercettato prima dell'invio.
Vincoli
Deve funzionare da un modulo web, da un link email e da una prenotazione telefonica inserita a mano; nessun passaggio può basarsi sull'orologio del dispositivo del client.
Casi limite
Slot occupato tra la visualizzazione e l'invio; re-invio col pulsante indietro; un professionista che va in ferie a metà sessione.
Compromessi
Ri-validare ogni passaggio costa una lettura free/busy in più ma elimina il guasto "lo slot che hai scelto non c'è più" alla conferma.
C2Motore di disponibilitàread model
Perché esiste
Calcola le finestre prenotabili per professionista a partire da orari di lavoro, margini, eventi esistenti e assenze — il read model da cui l'intero flusso viene renderizzato.
Architettura
Precalcola le finestre a intervalli programmati e sui webhook di modifica del calendario, memorizzandole in cache su Firestore; il flusso legge la cache, non la Calendar API, sul percorso caldo.
Vincoli
Deve restare corretto mentre i professionisti modificano direttamente i propri calendari; non deve superare la quota di lettura di Calendar sotto carico.
Casi limite
Eventi sovrapposti, blocchi per l'intera giornata, appuntamenti ricorrenti e limiti DST in cui una finestra delle "ore 9" si sposta.
Compromessi
Un TTL di cache breve baratta qualche secondo di obsolescenza con un forte calo delle chiamate API; il passaggio di conferma è l'autorità, quindi una breve obsolescenza è sicura.
C3API di prenotazione (riserva · verifica · conferma)core
Perché esiste
Il nucleo transazionale: trasforma una richiesta in esattamente un evento di calendario, in sicurezza, anche sotto concorrenza e ripetizioni.
Architettura
Ogni richiesta per un professionista passa attraverso la coda FIFO a consumatore singolo di quel professionista; confirm() controlla il free/busy dentro quella finestra e scrive con una chiave di idempotenza indirizzata al contenuto.
Contratto API
POST /booking  → 201 {eventId}  | 409 SlotTaken
// idempotent: same intent ⇒ same eventId
key = sha256(practitionerId, startUTC, clientId)
Casi limite
Richieste concorrenti per un singolo slot (serializzate via); ripetizioni di modulo/rete (collassate a un singolo evento tramite il registro); guasto parziale dopo l'inserimento (il commit del registro lo rende sicuro alla riesecuzione).
Compromessi
La serializzazione per singolo professionista aggiunge qualche ms di latenza e rimuove la corsa per costruzione — scelta al posto dei lock distribuiti.
C4Integrazione con Google CalendarWorkspace
Perché esiste
Mantiene Google Calendar come fonte di verità — leggendo il free/busy e scrivendo gli eventi — così che il team non lasci mai lo strumento che già usa.
Architettura
Usa la query aggregata freebusy per la disponibilità (nessun dettaglio dell'evento) e events.insert per le scritture, marcando ogni evento con la sua chiave di prenotazione in proprietà estese private.
Vincoli
Quote di lettura al minuto; scope a privilegio minimo; deve sopravvivere ai professionisti che modificano gli eventi a mano.
Casi limite
Eventi cancellati manualmente, condivisioni di calendari esterni e riconciliazione quando il calendario e il registro non concordano.
C5Gestione dei fusi oraricorrettezza
Perché esiste
Garantisce che uno slot significhi lo stesso istante per client, professionista e server attraverso i cambi dell'ora legale.
Architettura
Memorizza l'istante in UTC e la zona IANA voluta dall'utente come campo separato; i due si ricombinano solo al momento del rendering.
Casi limite
Salti di primavera/autunno, zone che osservano l'ora legale in date diverse e client che cambiano la zona del proprio dispositivo dopo la prenotazione.
Compromessi
Portarsi dietro una zona esplicita è più da memorizzare di un semplice timestamp, ma è l'unico modo per preservare la promessa "ore 9 a Lisbona."
C6Autenticazione e autorizzazionisicurezza
Perché esiste
Permette alla piattaforma di agire sui calendari del dominio con la minima autorità che un team di sicurezza approverà.
Architettura
Un service account dedicato con delega a livello di dominio strettamente circoscritta; ogni account risale a un proprietario e a un record di decisione.
Vincoli
Nessuno scope ampio; chiavi ruotate a intervalli programmati; accesso rivisto su calendario, non a memoria.
Compromessi
Il privilegio minimo comporta più configurazione a monte in cambio di un modello che supera la revisione senza eccezioni.
C7Notificheconsegna
Perché esiste
Conferma, ricorda e annulla sia per il client sia per il professionista senza mai inviare due volte.
Architettura
Consegna almeno-una-volta tramite Cloud Tasks con chiavi di idempotenza e una dead-letter queue, così che una ripetizione non invii mai due volte.
Casi limite
Throttling del provider, indirizzi rimbalzati e una prenotazione annullata prima che scatti il suo promemoria.
C8Generazione di Google MeetWorkspace
Perché esiste
Allega un link video funzionante a ogni prenotazione da remoto nel momento in cui l'evento viene creato.
Architettura
Richiede i dati della conferenza su events.insert così che il link Meet faccia parte della stessa scrittura atomica della prenotazione.
Casi limite
Guasti nella creazione della conferenza (la prenotazione deve comunque riuscire) ed eventi riprogrammati che mantengono il loro link.
C9Reportistica su Google Sheetsops
Perché esiste
Dà all'operatore una vista familiare e in tempo reale di prenotazioni e carico senza una dashboard su misura.
Architettura
Sincronizzazione in sola aggiunta dal registro verso un Sheet, trattato come una replica di lettura — mai una fonte di verità.
Compromessi
Uno Sheet è limitato e leggermente in ritardo, ma è immediatamente leggibile da un non-ingegnere, che è il punto.
04

Output visivo

Ciò che il sistema produce davvero per il cliente e per l'operatore. Questi sono reperti dal sistema in esecuzione, ciascuno con didascalia e collegato in modo incrociato al componente che lo crea. Inserisci gli screenshot reali nei riquadri.

Il flusso di prenotazione

Il percorso del cliente in tre passaggi: servizio e tempistica → dati di contatto → data e ora → conferma. Ogni passaggio ri-valida rispetto alla disponibilità in tempo reale.

Il flusso di prenotazione

Screenshot reale dal sistema in esecuzioneComponente: flusso di prenotazione a più passaggi

Il record del lead

Dove atterrano le risposte del passaggio di contatto: una riga aggiunta al Google Sheet — nome, azienda, email di lavoro, sorgente e timestamp di invio. Usa dati anonimizzati o di esempio.

Il record del lead

Screenshot reale · dati di esempio / anonimizzatiComponente: reportistica su Google Sheets

Evento di calendario creato

L'API di prenotazione scrive direttamente sul Google Calendar del professionista — titolo, orario, fuso orario, entrambi i partecipanti, un link Google Meet e il contesto dell'intake nella descrizione. La prova che il sistema crea un artefatto di calendario nativo, non una riga di database privato.

Evento di calendario creato

Componente: API di prenotazione · integrazione con Calendar

Invito e conferma per il cliente

Ciò che il cliente riceve — l'invito e la conferma di Google Calendar, con i dettagli della riunione e il link Meet.

Invito e conferma per il cliente

Screenshot reale · oscura i dati del destinatarioComponente: notifiche · generazione di Google Meet

Notifica interna

Ciò che il team vede quando arriva una prenotazione — la notifica interna con il contesto di qualificazione catturato e il flusso di lavoro di origine.

Screenshot reale — notifica interna di prenotazione

Screenshot reale · anonimizzatoComponente: notifiche

Guasto e recupero

Gli stati che dimostrano un pensiero orientato alla produzione: uno slot occupato tra la visualizzazione e l'invio, e la ripetizione riuscita che segue. A sinistra: conflitto. A destra: recupero.

Screenshot reale — stato di slot occupato / conflitto
Screenshot reale — ripetizione riuscita / recupero

Componente: API di prenotazione (disponibilità e concorrenza)

05

Impatto

Risultati oggettivi derivati dal mettere la piattaforma in produzione — prove, non marketing.

Business
  • Sostituito uno stack di pianificazione Calendly-più-Zapier con un unico sistema di proprietà.
  • Rimosso il costo ricorrente dell'abbonamento di terze parti e il collante che connetteva gli strumenti.
Cliente
  • Conferma immediata e affidabile nel momento della prenotazione.
  • Meno guasti di pianificazione — nessuno slot offerto che non possa essere onorato.
Operazioni
  • Prenotazioni duplicate eliminate.
  • Gestione dei fusi orari automatizzata da capo a fondo.
  • Inserimento manuale a calendario rimosso dalla giornata del team.
Ingegneria
  • Un'unica fonte di verità — nessun database di prenotazione parallelo che possa divergere.
  • Scritture idempotenti e sicure alla ripetizione; meno parti in movimento da operare.
Scala
  • ~4.000 prenotazioni / mese.
  • Zero doppie prenotazioni da quando è arrivata la serializzazione v2.
06

Documenti tecnici

Record ingegneristici cronologici scritti durante la costruzione della piattaforma — le decisioni, i vicoli ciechi e gli incidenti così come sono accaduti. Dai più recenti.

07

Case study

Una retrospettiva sulla piattaforma dal punto di vista aziendale — perché esiste, l'approccio adottato e come è andata a finire.

Problema
Un team di servizi gestiva il proprio calendario a mano e perdeva circa uno slot a settimana per doppie prenotazioni ed errori di fuso orario — poco costoso da contare, costosissimo in fiducia dei clienti.
Obiettivo
Rendere il calendario autoritativo e la prenotazione sicura, operabile da una sola persona, senza un secondo sistema di riferimento.
Vincoli
Google Calendar resta la fonte di verità; sicurezza a privilegio minimo; corretto sotto concorrenza e ripetizioni; entro le quote della Calendar API.
Approccio
Un coordinatore sottile e senza stato davanti alla Calendar API; serializzazione per singolo professionista per rimuovere la corsa; idempotenza indirizzata al contenuto per rimuovere i duplicati; UTC-più-intento per il tempo.
Architettura
Intake → validazione all'edge → coda FIFO per singolo professionista → coordinatore riserva/verifica/conferma → Google Calendar, con un piccolo registro di idempotenza. Nessun database di prenotazione parallelo.
Compromessi
Scelta una coda noiosa e dimostrabilmente corretta al posto dei lock distribuiti; accettati alcuni secondi di obsolescenza della disponibilità per un grande risparmio di quota; mantenuto lo stato nella piattaforma che già lo possiede.
Esito
In produzione da feb 2024, ~4.000 prenotazioni/mese, zero doppie prenotazioni da quando è arrivata la serializzazione v2; "la mia prenotazione è andata a buon fine?" è diventato un non-evento perché le ripetizioni sono sicure.
Lezioni
  • Serializza la risorsa contesa; non bloccare il mondo.
  • L'idempotenza è una funzionalità, non una salvaguardia.
  • Lascia che la piattaforma mantenga lo stato che già possiede.
Futuro
Un flusso di riprogrammazione self-service, e spostare la pulizia del TTL del registro dal cron alla scadenza del documento.
← Tutti i progetti