Accueil / Projets / Plateforme de réservation

Remplacer Typeform, Calendly et Zapier par une seule plateforme de réservation

Un seul système possédé a remplacé trois abonnements SaaS récurrents — Typeform, Calendly et Zapier — en déplaçant l'ensemble du flux de réservation à l'intérieur de Google Workspace, personnalisable à chaque étape et dépendant d'aucun prestataire externe.

Statut En production · v3.2
Échelle~4,000 réservations / mois
Technologies principalesGoogle Calendar API · Google Sheets API · Google Apps Script · TypeScript
01

Vue d'ensemble

Un système de planification qui permet à une équipe de services distribuée de prendre des réservations auprès de nombreux praticiens sans jamais doubler une réservation, mal gérer un fuseau horaire ou dupliquer un rendez-vous lors d'une nouvelle tentative — avec Google Calendar comme unique source de vérité.

Ce qui a été construit

Une plateforme de réservation posée directement sur Google Workspace. Les clients choisissent un créneau parmi les disponibilités calculées ; la plateforme réserve, vérifie et confirme le rendez-vous en une seule transaction idempotente, écrivant l'événement dans le Google Calendar du praticien et prévenant les deux parties. Il n'y a pas de base de données de référence distincte — l'agenda dans lequel l'équipe vit déjà reste la référence.

À qui il s'adresse

Une entreprise de services faisant travailler plusieurs praticiens, chacun avec ses propres horaires de travail, tampons et congés, prenant des réservations depuis un formulaire web, par e-mail et par l'occasionnel appel téléphonique saisi après coup.

Contexte métier

Le processus manuel qu'elle a remplacé perdait environ un créneau par semaine à cause des doubles réservations et des décalages de fuseau horaire — peu nombreux, mais coûteux en confiance. Le rôle de la plateforme était de rendre l'agenda faisant autorité et la réservation sûre, sans ajouter un second système qui finirait par se désynchroniser.

02

Architecture

Un coordinateur mince et sans état devant Google Calendar. Une réservation est une transaction courte et idempotente — réserver, vérifier, confirmer — acheminée à travers une file d'attente par praticien, afin que la concurrence qui provoque la double réservation ne puisse pas se produire.

Clientformulaire web / accueil par e-mail
EdgeCloud Function — valider + normaliser le TZ
File d'attenteCloud Tasks — FIFO par praticien
↓ une réservation à la fois, par praticien ↓
Coordinateurréserver → vérifier → confirmer
RegistreFirestore — clés d'idempotence (TTL)
Source de véritéGoogle Calendar — freebusy + événements

Pourquoi une file d'attente par praticien

La double réservation est une concurrence entre écrivains simultanés pour une même ressource. Plutôt que de recourir à des verrous distribués, chaque requête pour un praticien donné passe par une file d'attente FIFO à consommateur unique — une primitive ennuyeuse et débogable qui rend la concurrence impossible plutôt que simplement réparable. La concurrence entre praticiens reste élevée ; au sein d'un même praticien, elle tombe à un.

03

Composants

La plateforme est bâtie à partir de neuf composants. Chacun est documenté comme sa propre section d'ingénierie — pourquoi il existe, son architecture, les contraintes et cas limites qu'il gère, les compromis retenus et l'implémentation finale. Dépliez-en un pour le lire.

C1Flux de réservation multi-étapescôté client
Pourquoi il existe
Transforme « trouver un horaire » en une séquence guidée et reprenable — service → praticien → date → créneau → détails → confirmation — qui ne présente jamais un créneau qu'elle ne peut pas honorer.
Architecture
Un client sans état piloté par le moteur de disponibilité ; chaque étape se revalide en temps réel contre le free/busy, si bien qu'un créneau qui se remplit en cours de flux est détecté avant la soumission.
Contraintes
Doit fonctionner depuis un formulaire web, un lien e-mail et une réservation téléphonique saisie à la main ; aucune étape ne peut se fier à l'horloge de l'appareil du client.
Cas limites
Créneau pris entre l'affichage et la soumission ; re-soumission par le bouton retour ; un praticien partant en congé en cours de session.
Compromis
Revalider chaque étape coûte une lecture free/busy supplémentaire, mais élimine l'échec « le créneau que vous avez choisi n'est plus disponible » au moment de la confirmation.
C2Moteur de disponibilitémodèle de lecture
Pourquoi il existe
Calcule les fenêtres réservables par praticien à partir des horaires de travail, tampons, événements existants et congés — le modèle de lecture à partir duquel tout le flux s'affiche.
Architecture
Précalcule les fenêtres selon une planification et sur les webhooks de changement d'agenda, en les mettant en cache dans Firestore ; le flux lit le cache, et non l'API Calendar, sur le chemin critique.
Contraintes
Doit rester correct pendant que les praticiens modifient directement leurs propres agendas ; ne doit pas dépasser le quota de lecture Calendar sous charge.
Cas limites
Événements qui se chevauchent, blocs d'une journée entière, blocages récurrents et frontières DST où une fenêtre « 9 h » se décale.
Compromis
Un TTL de cache court échange quelques secondes d'obsolescence contre une forte baisse des appels d'API ; l'étape de confirmation fait autorité, donc une brève obsolescence est sans danger.
C3API de réservation (réserver · vérifier · confirmer)cœur
Pourquoi il existe
Le cœur transactionnel : transforme une requête en exactement un événement d'agenda, en toute sûreté, même sous concurrence et nouvelles tentatives.
Architecture
Chaque requête pour un praticien passe par la file d'attente FIFO à consommateur unique de ce praticien ; confirm() vérifie le free/busy à l'intérieur de cette fenêtre et écrit avec une clé d'idempotence adressée par le contenu.
Contrat d'API
POST /booking  → 201 {eventId}  | 409 SlotTaken
// idempotent: same intent ⇒ same eventId
key = sha256(practitionerId, startUTC, clientId)
Cas limites
Requêtes simultanées pour un même créneau (sérialisées et éliminées) ; nouvelles tentatives de formulaire/réseau (fusionnées en un seul événement via le registre) ; échec partiel après l'insertion (la validation du registre le rend sûr au rejeu).
Compromis
La sérialisation par praticien ajoute quelques ms de latence et supprime la concurrence par construction — choisie plutôt que des verrous distribués.
C4Intégration Google CalendarWorkspace
Pourquoi il existe
Maintient Google Calendar comme source de vérité — en lisant le free/busy et en écrivant les événements — pour que l'équipe ne quitte jamais l'outil qu'elle utilise déjà.
Architecture
Utilise la requête agrégée freebusy pour la disponibilité (sans détail d'événement) et events.insert pour les écritures, marquant chaque événement de sa clé de réservation dans des propriétés étendues privées.
Contraintes
Quotas de lecture à la minute ; portées au moindre privilège ; doit survivre aux praticiens modifiant les événements à la main.
Cas limites
Événements supprimés manuellement, partages d'agenda externes et réconciliation lorsque l'agenda et le registre divergent.
C5Gestion des fuseaux horairesexactitude
Pourquoi il existe
Garantit qu'un créneau désigne le même instant pour le client, le praticien et le serveur à travers les changements d'heure d'été.
Architecture
Stocke l'instant en UTC et la zone IANA voulue par l'utilisateur dans un champ distinct ; les deux ne se recombinent qu'au rendu.
Cas limites
Trous d'avance/de recul horaire, zones qui observent le DST à des dates différentes, et clients changeant le fuseau de leur appareil après la réservation.
Compromis
Porter une zone explicite est plus lourd à stocker qu'un simple horodatage, mais c'est la seule manière de préserver la promesse « 9 h à Lisbonne ».
C6Authentification et permissionssécurité
Pourquoi il existe
Permet à la plateforme d'agir sur les agendas du domaine avec la moindre autorité qu'une équipe de sécurité acceptera de valider.
Architecture
Un compte de service dédié avec une délégation à l'échelle du domaine étroitement délimitée ; chaque compte remonte à un propriétaire et à un registre de décision.
Contraintes
Aucune portée large ; clés renouvelées selon une planification ; accès revu sur un calendrier, et non de mémoire.
Compromis
Le moindre privilège demande davantage de configuration en amont, en échange d'un modèle qui passe la revue sans exceptions.
C7Notificationsdiffusion
Pourquoi il existe
Confirme, rappelle et annule pour le client comme pour le praticien, sans jamais envoyer deux fois.
Architecture
Diffusion au moins une fois via Cloud Tasks avec des clés d'idempotence et une file de rebut, si bien qu'une nouvelle tentative n'envoie jamais en double.
Cas limites
Limitation par le fournisseur, adresses en échec de remise, et une réservation annulée avant le déclenchement de son rappel.
C8Génération de Google MeetWorkspace
Pourquoi il existe
Attache un lien vidéo fonctionnel à chaque réservation à distance au moment de la création de l'événement.
Architecture
Demande les données de conférence lors de events.insert pour que le lien Meet fasse partie de la même écriture atomique que la réservation.
Cas limites
Échecs de création de conférence (la réservation doit tout de même aboutir) et événements reprogrammés conservant leur lien.
C9Reporting Google Sheetsops
Pourquoi il existe
Donne à l'opérateur une vue familière et en direct des réservations et de la charge, sans tableau de bord sur mesure.
Architecture
Synchronisation en ajout seul depuis le registre vers un Sheet, traité comme une réplique de lecture — jamais comme une source de vérité.
Compromis
Un Sheet est limité et légèrement en retard, mais il est instantanément lisible par un non-ingénieur, ce qui est tout l'intérêt.
04

Rendu visuel

Ce que le système produit réellement pour le client et l'opérateur. Ce sont des pièces issues du système en fonctionnement — chacune légendée et reliée au composant qui la crée. Déposez les vraies captures d'écran dans les cadres.

Le flux de réservation

Le parcours client en trois étapes : service et horaire → coordonnées → date et heure → confirmation. Chaque étape se revalide contre la disponibilité en direct.

Le flux de réservation

Vraie capture d'écran du système en fonctionnementComposant : Flux de réservation multi-étapes

La fiche de prospect

Où atterrissent les réponses de l'étape de contact : une ligne ajoutée au Google Sheet — nom, entreprise, e-mail professionnel, source et horodatage de soumission. Utilisez des données anonymisées ou d'exemple.

La fiche de prospect

Vraie capture d'écran · données d'exemple / anonymiséesComposant : Reporting Google Sheets

Événement d'agenda créé

L'API de réservation écrit directement dans le Google Calendar du praticien — titre, heure, fuseau horaire, les deux participants, un lien Google Meet et le contexte d'accueil dans la description. La preuve que le système crée un artefact d'agenda natif, et non une ligne de base de données privée.

Événement d'agenda créé

Composant : API de réservation · Intégration Calendar

Invitation et confirmation du client

Ce que reçoit le client — l'invitation et la confirmation Google Calendar, avec les détails de la réunion et le lien Meet.

Invitation et confirmation du client

Vraie capture d'écran · masquer les coordonnées du destinataireComposant : Notifications · Génération de Google Meet

Notification interne

Ce que voit l'équipe quand une réservation arrive — la notification interne avec le contexte de qualification capturé et le flux source.

Vraie capture d'écran — notification interne de réservation

Vraie capture d'écran · anonymiséeComposant : Notifications

Échec et reprise

Les états qui prouvent une pensée orientée production : un créneau pris entre l'affichage et la soumission, et la nouvelle tentative réussie qui suit. À gauche : le conflit. À droite : la reprise.

Vraie capture d'écran — état créneau pris / conflit
Vraie capture d'écran — nouvelle tentative réussie / reprise

Composant : API de réservation (disponibilité et concurrence)

05

Impact

Résultats objectifs issus de la mise en production de la plateforme — des preuves, pas du marketing.

Business
  • A remplacé une pile de planification Calendly-plus-Zapier par un seul système possédé.
  • A supprimé le coût d'abonnement tiers récurrent et la glu reliant les outils.
Client
  • Confirmation immédiate et fiable au moment de la réservation.
  • Moins d'échecs de planification — aucun créneau proposé qui ne puisse être honoré.
Opérations
  • Réservations en double éliminées.
  • Gestion des fuseaux horaires automatisée de bout en bout.
  • Saisie manuelle dans l'agenda retirée du quotidien de l'équipe.
Ingénierie
  • Une unique source de vérité — aucune base de données de réservation parallèle qui dérive.
  • Écritures idempotentes, sûres au rejeu ; moins de pièces mobiles à exploiter.
Échelle
  • ~4,000 réservations / mois.
  • Zéro double réservation depuis l'arrivée de la sérialisation v2.
06

Documents techniques

Dossiers d'ingénierie chronologiques écrits pendant la construction de la plateforme — les décisions, impasses et incidents tels qu'ils se sont produits. Du plus récent au plus ancien.

07

Étude de cas

Une rétrospective sur la plateforme du point de vue métier — pourquoi elle existe, l'approche adoptée et comment cela s'est passé.

Problème
Une équipe de services gérait son agenda à la main et perdait environ un créneau par semaine à cause des doubles réservations et des erreurs de fuseau horaire — peu coûteux à compter, coûteux en confiance client.
Objectif
Rendre l'agenda faisant autorité et la réservation sûre, exploitable par une seule personne, sans second système de référence.
Contraintes
Google Calendar reste la source de vérité ; sécurité au moindre privilège ; correct sous concurrence et nouvelles tentatives ; dans les limites des quotas de l'API Calendar.
Approche
Un coordinateur mince et sans état devant l'API Calendar ; sérialisation par praticien pour supprimer la concurrence ; idempotence adressée par le contenu pour supprimer les doublons ; UTC-plus-intention pour l'heure.
Architecture
Accueil → validation en périphérie → file d'attente FIFO par praticien → coordinateur réserver/vérifier/confirmer → Google Calendar, avec un petit registre d'idempotence. Aucune base de données de réservation parallèle.
Compromis
Choix d'une file d'attente ennuyeuse et prouvée correcte plutôt que de verrous distribués ; acceptation de quelques secondes d'obsolescence de disponibilité pour une forte économie de quota ; état conservé dans la plateforme qui le possède déjà.
Résultat
En production depuis Feb 2024, ~4,000 réservations/mois, zéro double réservation depuis l'arrivée de la sérialisation v2 ; « ma réservation est-elle bien passée ? » est devenu un non-événement, parce que les nouvelles tentatives sont sûres.
Enseignements
  • Sérialisez la ressource en contention ; ne verrouillez pas le monde entier.
  • L'idempotence est une fonctionnalité, pas un garde-fou.
  • Laissez la plateforme conserver l'état qu'elle possède déjà.
Suite
Un flux de reprogrammation en libre-service, et le déplacement du nettoyage TTL du registre depuis cron vers l'expiration des documents.
← Tous les projets