Architecture Next.js + Cal.com + n8n : un site qui book tout seul
Next.js + Cal.com + n8n : la stack qui transforme un site vitrine en machine à RDV. Embed, API v2, webhooks HMAC, événement bookingSuccessfulV2. Architecture complète et pièges 2026.
Architecture Next.js + Cal.com + n8n : un site qui book tout seul
Un site vitrine qui ne prend pas de RDV n'est qu'une brochure en ligne. Trois briques le transforment en machine à leads.
Un prospect arrive sur votre site à 22 h. Sur un site classique, il remplit un formulaire, puis... il attend votre email du lendemain. Déjà passé à un concurrent. Et le formule Google d'un·e assis·e vous compare à celui qui répond « Maintenant », à minuit.
La prise de rendez-vous en ligne est le meilleur levier de conversion d'un site pour les services. Mais la plupart des guides — et je les ai audités — s'arrêtent à « utilisez un plugin » ou « mettez un lien Calendly ». Personne ne montre l'architecture complète : comment le site Next.js, le calendrier Cal.com et l'automatisation n8n travaillent ensemble, sans fuite de données et sans botte de réservations fantômes.
Cet article code la stack Next.js + Cal.com + n8n, pièce par pièce : l'embed qui garde l'utilisateur sur votre site, l'API v2 pour les flows custom, les webhooks vérifiés par signature HMAC, et l'événement bookingSuccessfulV2 qui déclenche une action dans l'app dès le RDV réservé. À la fin, la stack, le tableau des pièges, et le créneau de 30 min pour l'appliquer à votre domaine.
Pourquoi cette stack, et pas un plugin
Les 10 premiers résultats de « prise de rendez-vous en ligne » sont des vendeurs : Mobirise (générateur IA), Wegic, Rendevoo, botnation. Ou des listicles SaaS (HubSpot, 18 logiciels). Un seul — simplebo — parle de la technique sérieusement, mais reste au niveau vitrine.
La stack Next.js + Cal.com + n8n gagne à trois niveaux qu'un plugin ne couvre pas :
- Le run, pas le label. Vous maîtrisez le parcours, l'URL, le SEO, le tracking. Vous n'êtes pas enfermé dans la page d'un SaaS généré.
- Le cycle complet du RDV. Pas seulement « créer une résa » : rappels, reschedule, no-show, notification CRM. C'est là que n8n entre en jeu.
- La donnée reste vôtre. Vous contrôlez qui reçoit quoi (email, Slack, CRM), et où (propre infra).
Un plugin WordPress fait apparaître un bouton « Réserver ». Cette stack transforme le site en système qui encaisse la demande, la planifie, la notifie, et la suit — sans humain au milieu.
Un visiteur arrive, voit vos créneaux, réserve dans l'embed, et une confirmation Webhook part automatiquement. Aucun intermédiaire humain.
Les trois briques, et leur rôle
| Brique | Rôle | Ne fait PAS |
|---|---|---|
| Next.js | Le site, le SEO, l'UX, l'embed, les routes API | L'agenda, la timezone, les emails |
| Cal.com | Le moteur de réservation (embeddable, open source) | Le traitement métier post-RDV |
| n8n | L'automatisation (workflows, webhooks, CRM, Slack, email) | La logique d'affichage du site |
La séparation des responsabilités est le cœur de l'architecture. Next.js reste léger : il affiche du contenu indexable (SSR/SSG) et embarque le widget. Cal.com gère toute la complexité du calendrier (fuseaux horaires, disponibilités, rappels email). n8n orchestre ce qui doit se passer après le RDV.
Pourquoi ne pas tout faire dans Next.js ? Parce que la planification et l'automatisation changeront indépendamment de votre site. Vous redesignerez la home — pas la logique de rappel. Découpler les trois vous évite de réécrire le booking à chaque refonte.
Étape 1 — Embarquer Cal.com dans Next.js
Cal.com fournit trois packages : @calcom/embed-core (vanilla JS), @calcom/embed-snippet (snippet léger), et @calcom/embed-react (composant React + TypeScript). Pour un site Next.js, c'est le React qu'il faut.
Installation
npm install @calcom/embed-react
Le composant
import Cal from "@calcom/embed-react";
export default function BookingSection() {
return (
<Cal
calLink="votre-equipe/appel-decouverte"
style={{ width: "100%", height: "600px" }}
config={{
theme: "light",
hideEventTypeDetails: false,
layout: "month_view",
}}
/>
);
}
Écouter les événements
import { getCalApi, type EmbedEvent } from "@calcom/embed-react";
useEffect(() => {
(async () => {
const cal = await getCalApi({ namespace: "inline" });
cal("on", {
action: "bookingSuccessfulV2",
callback: (e: EmbedEvent<"bookingSuccessfulV2">) => {
const data = e.detail.data;
console.log("RDV créé:", {
title: data.title,
startTime: data.startTime,
endTime: data.endTime,
});
},
});
return () => cal("off", {
action: "bookingSuccessfulV2",
callback: myCallback,
});
})();
}, []);
Ce que l'embed fait pour vous
- Garde l'utilisateur dans votre site, pas de redirect vers une page Cal.com séparée.
- Communication par événements namespacés : le parent et l'iframe se parlent via un système de messages. Plusieurs embeds peuvent coexister sur une page sans interférer (namespaces).
- Instruction queue : les commandes sont mises en file tant que l'iframe n'est pas prête, puis exécutées. Aucune commande perdue pendant l'initialisation.
- Thème et marque :
configvous permet d'aligner couleurs et layout. Pour un contrôle total, enveloppez dans une iframe isolée.
Un piège courant : plusieurs .Cal avec le même calLink sur une page peuvent se renvoyer les événements. Utilisez un namespace distinct par instance.
Le composant Cal de @calcom/embed-react : calLink, style, config. Les événements bookingSuccessfulV2 remontent au parent via le namespace.
Étape 2 — Le post-RDV : webhooks Cal.com → n8n
L'embed vit côté client. Pour une action fiable côté serveur (créer un lead CRM, envoyer un email, notifier Slack), vous avez besoin d'un webhook.
Le piège n°1 : le node Cal.com Trigger et l'API v1
Le node n8n Cal.com Trigger a longtemps reposé sur l'API v1 de Cal.com. Cette API est dépréciée. Selon votre version de n8n, le node peut pointer vers des endpoints morts et casser silencieusement. La migration vers l'API v2 arrive, mais en attendant, la solution robuste est :
Créer un node Webhook n8n générique et l'enregistrer comme URL de callback dans Cal.com.
Le piège n°2 : la signature HMAC
Un webhook est une URL publique. N'importe qui peut l'appeler. Cal.com signe chaque payload avec un HMAC-SHA256 de votre secret, envoyé dans le header X-Cal-Signature-256. Vous devez vérifier cette signature avant de traiter la donnée.
Exemple de route webhook Next.js
// app/api/webhooks/cal/route.ts
import { createHmac } from "crypto";
export async function POST(request: Request) {
const body = await request.json();
const signature = request.headers.get("X-Cal-Signature-256");
const expectedSig = createHmac("sha256", process.env.CAL_WEBHOOK_SECRET!)
.update(JSON.stringify(body))
.digest("hex");
if (signature !== expectedSig) {
return new Response("Unauthorized", { status: 401 });
}
const { triggerEvent, payload } = body;
switch (triggerEvent) {
case "BOOKING_CREATED":
await handleBookingCreated(payload);
break;
case "BOOKING_CANCELLED":
await handleBookingCancelled(payload);
break;
case "BOOKING_RESCHEDULED":
await handleBookingRescheduled(payload);
break;
}
return new Response("OK");
}
Un exemple de webhook n8n
Cal.com couvre tout le cycle de vie d'un RDV. Configurez les webhooks dans /settings/developer/webhooks, et choisissez les triggers qui vous servent :
| Événement | Quand il se déclenche |
|---|---|
BOOKING_CREATED | Nouveau RDV confirmé |
BOOKING_RESCHEDULED | Le participant a changé l'heure |
BOOKING_CANCELLED | RDV annulé |
MEETING_STARTED | L'appel vidéo a commencé |
MEETING_ENDED | L'appel vidéo est terminé |
RECORDING_READY | L'enregistrement est disponible |
Le payload contient : infos participant, détails de l'événement, et votre metadata custom.
Cal.com signe le payload avec X-Cal-Signature-256. Le webhook n8n (ou la route Next.js) vérifie le HMAC, puis la chaîne d'automatisation démarre.
Étape 3 — Le workflow n8n de bout en bout
Une fois le webhook reçu et vérifié, n8n orchestre. Un workflow type pour une PME :
- Webhook (reçoit BOOKING_CREATED, vérifié HMAC).
- Transform : mapper les champs Cal.com vers le schéma de votre CRM (nom, email, date, message).
- HTTP Request : POST vers votre CRM (HubSpot, Pipedrive, ou votre API maison).
- Slack/Email : notifier l'équipe en temps réel, + email de confirmation et rappels programmés.
Cette chaîne tourne sans intervention humaine. Vous récupérez le RDV dans le CRM, votre équipe est notifiée à l'instant T, et le no-show est traité par un rappel automatique.
Self-hosting = contrôle total
Les briques sont open source. Vous pouvez héberger Cal.com et n8n sur votre propre infra. Dans ce cas, le webhook passe directement de Cal.com à n8n, sans passer par Vercel : la donnée ne quitte jamais votre infrastructure. C'est le setup le plus « souverain », avec un coût d'exploitation à assumer.
Embded + webhook = les deux gains
- Côté client (embed) : UX immédiate, pas de latence. L'événement
bookingSuccessfulV2affiche une confirmation ou déclenche un CTA dans la page. - Côté serveur (webhook) : automatisation fiable, gardée même si l'onglet fermé. La source de vérité pour CRM et notifications.
N'utilisez pas l'événement client pour l'automatisation critique. Il dépend d'un navigateur ouvert. Le webhook, lui, est déclenché par Cal.com côté serveur, quoi qu'il arrive.
Webhook n8n reçoit le RDV → transforme → POST CRM → notifie Slack/email. Une chaîne complète sans humain.
API v2 : quand l'embed ne suffit plus
Pour un contrôle total, l'API v2 de Cal.com remplace l'embed. Vous construisez votre propre formulaire, avec vos règles métier, et Cal.com gère la lourdeur.
Les points de l'API v2
// Avec l'API v2
const res = await fetch("https://api.cal.com/v2/bookings", {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"cal-api-version": "2024-08-13",
"Content-Type": "application/json",
},
body: JSON.stringify({
eventTypeId: eventTypeId,
start: startISO,
attendee: { name, email, timeZone },
metadata: {}, // contexte perso
}),
});
Le header cal-api-version est obligatoire. Il stabilise l'API pour sonor le versioning.
Le champ metadata
Le metadata est votre allié. Vous y collez du contexte propre à votre app : id utilisateur, numéro de commande, source, segment. Ce contexte survit à la réservation et apparaît dans les webhooks — vous reliez chaque RDV à une situation métier, sans état parallèle.
Embed ou API v2 ?
| Critère | Embed (@calcom/embed-react) | API v2 |
|---|---|---|
| Mise en place | Rapide | Moyenne |
| Form custom / pré-collecte | Limitée | Totale |
| Garde l'utilisateur | Oui | Oui |
| Coût de maintenance | Faible | Plus élevé |
| Quand choisir | PME qui veut partir vite | App avec règles spécifiques |
Le tableau des pièges 2026
| Piège | Impact | Correctif |
|---|---|---|
| Node n8n Cal.com Trigger = API v1 | Casse silencieuse du workflow | Webhook n8n générique + HMAC |
| Signature HMAC non vérifiée | N'importe qui poste des faux RDV | X-Cal-Signature-256 vérifié, sinon 401 |
cal-api-version manquant (API v2) | Appel rejeté | Header cal-api-version: 2024-08-13 |
| Plusieurs embeds sans namespace | Événements croisés | Namespace distinct par instance |
| Compter sur l'événement client pour le CRM | Perte si onglet fermé | Webhook serveur comme source de vérité |
| CoEP credentialless sur Next.js | L'iframe Cal.com bloquée | Vérifier les headers si vous mixez embeds |
Le dernier point est important : si vous combinez l'embed Cal.com avec des headers de sécurité exigeants (COEP credentialless, voir la logique Flutter Wasm), l'iframe peut être bloquée. Testez l'embed dans votre environnement de prod, pas seulement en local.
Next.js (site, embed, routes API) + Cal.com (moteur de réservation) + n8n (automatisation post-RDV). Séparés, mais connectés par webhooks HMAC.
Checklist de mise en place
- Créer le compte Cal.com et le type d'événement (appel de 30 min).
npm install @calcom/embed-react.- Intégrer le composant
Caldans la section booking de votre page. - Écouter
bookingSuccessfulV2pour l'UX post-réservation. - Créer un workflow n8n vide, commencer par un node Webhook.
- Copier l'URL n8n production (ou créer une route
app/api/webhooks/cal/route.ts). - Dans
/settings/developer/webhooksCal.com, enregistrer l'URL et choisir les triggers. - Activer et vérifier la signature HMAC du payload.
- Ajouter les nodes : Transform → HTTP Request (CRM) → Slack/Email.
- Tester en staging avec un RDV bidon, vérifier CRM + notification.
- Mesurer le taux de RDV (CTA clair avant l'embed).
- Itérer sur le rappel no-show et le reschedule.
Ce que la stack ne fait PAS
- Remplacer le marketing. La friction disparaît, pas le besoin de trafic.
- Répondre aux emails. L'automatisation gère le RDV, pas la relation.
- Garantir le taux de conversion. Un CTA flou ou une page lente tuent la résa, même avec un embed parfait.
- Être une solution unique pour tous. Un site de conseil gagne avec Cal.com ; une pro de santé avec un dossier médical a besoin de plus.
Conclusion
La stack Next.js + Cal.com + n8n n'est pas une question de gadgets. C'est le moyen de faire travailler ensemble un site moderne (SEO, UX, indexation) et un moteur de réservation fiable, avec une automatisation qui encaisse et suit chaque RDV.
Trois niveaux, trois livrables :
- Embed
@calcom/embed-react— garde le visiteur, affiche vos créneaux. - Webhook HMAC — transmet le RDV au serveur, en sécurité.
- Workflow n8n — CRM, notifications, rappels, suivi.
Si vous avez un site vitrine qui « présente mais ne prend pas de RDV », c'est précisément le fossé que cette stack comble. La brique qui manque à votre conversion n'est pas le design — c'est souvent un RDV qui se réserve à minuit, sans vous.
Prenez RDV — 30 min : on regarde votre site, les 3 fuites, et on vous dit si l'embed suffit ou s'il faut brancher l'API v2 + n8n. Sans engagement.
Références : Cal.com Embed overview (calcom-cal-com.mintlify.app) · Cal.com embed-react (mintlify.wiki) · Cal.com API v2 bookings (nextfuture.io.vn) · Cal.com API webhooks (blog.elest.io)
Étiquettes
FAQ
Peut-on embarquer Cal.com dans un site Next.js sans externaliser ?
Oui. Le package @calcom/embed-react fournit un composant React (Cal) et une fonction getCalApi. L'embed gère la synchronisation calendrier, fuseaux horaires et notifications. Le parent et l'iframe communiquent par des événements namespacés, exécutés via une instruction queue (aucune commande perdue pendant l'init). Pour un contrôle total du flow de réservation, utilisez l'API v2 au lieu de l'embed.
Les webhooks Cal.com sont-ils sécurisés avec n8n ?
Oui, si vous vérifiez la signature HMAC. Cal.com envoie un header X-Cal-Signature-256. Refusez toute requête dont la signature ne matche pas le HMAC-SHA256 de votre secret (return 401). En parallèle, créez un node Webhook n8n générique : il est plus fiable que le node Cal.com Trigger, qui reposait sur l'API v1 et peut casser selon votre version n8n. Enregistrez l'URL n8n production dans les webhooks Cal.com et choisissez les triggers BOOKING_CREATED / BOOKING_CANCELLED / BOOKING_RESCHEDULED.
Comment déclencher une action dans l'app après un RDV réservé ?
Écoutez l'événement bookingSuccessfulV2 de l'embed (Cal("on", { action: "bookingSuccessfulV2" })). Le payload contient title, startTime, endTime. Vous pouvez aussi jauger les actions côté serveur via les webhooks. Pour un CTA post-booking sans latence, combinez les deux : événement client pour l'UX immédiate, webhook serveur pour l'automatisation fiable (CRM, email, lead).
Vaut-il mieux l'embed ou l'API v2 de Cal.com ?
Ça dépend. L'embed (@calcom/embed-react) est rapide à mettre en place, garde l'utilisateur dans votre site, et gère la lourdeur (calendrier, timezone). L'API v2 (/v2/bookings avec header cal-api-version: 2024-08-13 et Bearer token) donne un contrôle total : formulaire custom, pré-collecte de données avec le champ metadata, flow intégré. Pour une PME qui veut partir vite : embed. Pour une app avec des règles métier spécifiques : API v2.
Où héberger les webhooks Cal.com si on a Next.js chez Vercel ?
Deux options. (1) À côté de l'app : une route app/api/webhooks/cal/route.ts dans Next.js, qui vérifie X-Cal-Signature-256 puis appelle n8n. (2) Directement vers n8n si vous l'exposez (webhook n8n en URL de callback). Le plus robuste : webhook n8n générique + HMAC, car le node Cal.com Trigger peut dépendre de l'API v1 dépréciée. Testez en staging avant de brancher la production.
La prise de RDV en ligne réduit-elle vraiment le coût par lead ?
L'automatisation du cycle RDV (création, rescheduled, no-show, rappels) réduit le travail humain de planification. Le gain est net sur le volume : plus de double-prise, pas de rebook à la main, rappels automatiques. Mais l'architecture seule ne suffit pas — le taux de conversion dépend aussi du parcours (CTA clair, avis, temps de réponse). La stack Next.js + Cal.com + n8n supprime la friction, elle ne remplace pas le marketing.
Votre site prend-il des rendez-vous — ou il présente ?
On ouvre votre URL ensemble, on pointe les 3 fuites, on vous dit si une optimisation suffit ou s’il faut refondre.
- 30 min
- Sans engagement
- Plan d’action

William Aklamavo
Expert en développement web et automatisation, passionné par l'innovation technologique et l'entrepreneuriat digital.
