ADR: Intégration de la Newsletter avec Loops, Cloudflare Queues et Sanity
ADR: Intégration de la Newsletter avec Loops, Cloudflare Queues et Sanity
Architecture de gestion de la newsletter du prefooter : intégration de Loops (CRM/emailing), Cloudflare Queues (asynchrone) et Sanity (contenus & audit).
- Statut : Proposé (En attente de validation)
- Date : 2026-10-26
- Auteur : Antigravity & Architecture AMN
- Projet : AMN (amn-blog, amn-studio, amn-services, amn-docs)
1. Contexte et Problématique1/2
Le composant PreFooter.astro de amn-blog contient un formulaire d’inscription à la newsletter. Les textes et libellés sont administrables depuis Sanity via le singleton prefooterSettings, mais le traitement métier de l’inscription était jusqu’ici factice ou non relié à un outil d’emailing dédié.
1. Contexte et Problématique2/2
Le projet AMN repose sur une architecture composable stricte :
- Couche 01 (Contenu) : Sanity CMS (schémas, textes, modération et piste d’audit).
- Couche 02 (Présentation) : Astro SSR sur Cloudflare Pages/Workers (UI responsive, micro-animations, Stega clean, accessibilité).
- Couche 03 (Services & Backend) : Cloudflare Workers, Service Bindings et Cloudflare Queues.
Pour la gestion marketing de l’audience et des emails transactionnels, la plateforme Loops.so (forfait Free) a été retenue avec une clé API dédiée.
Exigences clés :
- Fluidité & Performance UI : Réponse utilisateur quasi-instantanée (< 50ms) sans latence réseau liée aux API tierces.
- Résilience & Tolérance aux pannes : En cas d’indisponibilité temporaire de Loops ou de Sanity, aucune inscription ne doit être perdue.
- Respect de l’architecture composable : Aucun secret ou clé API tierce exposée côté client, tout passe par le backend L3 Cloudflare.
- Outillage MCP Loops : Pouvoir interagir avec le compte Loops depuis l’environnement de développement et les agents AI via le Model Context Protocol.
2. Décisions Architecturales
2.1. Plateforme d’Emailing : Loops.so (Plan Free)
Nous intégrons Loops.so comme fournisseur de gestion des contacts, des listes d’attente et des campagnes d’envoi. Les nouveaux inscrits sont enregistrés avec le statut subscribed: true et le groupe utilisateur userGroup: "Newsletter".
2.2. Configuration du Serveur MCP Loops (Résolution Technique)1/3
L’URL distante officielle https://mcp.loops.so implémente exclusivement l’authentification OAuth 2.0 PKCE interactive via navigateur et rejette les clés API statiques (retour HTTP 401 loops rejected token: invalid token).
Décision : Pour permettre aux agents et à l’IDE d’administrer le compte Loops avec la clé API fournie (796e3ae3c6da58a59e14787256ce0507), nous configurons le serveur MCP stdio officiel de la communauté :
2.2. Configuration du Serveur MCP Loops (Résolution Technique)2/3
{ "mcpServers": { "loops": { "command": "npx", "args": ["-y", "loops-mcp-server"], "env": { "LOOPS_API_KEY": "796e3ae3c6da58a59e14787256ce0507" } } }}2.2. Configuration du Serveur MCP Loops (Résolution Technique)3/3
Ce serveur expose les outils loops_create_contact, loops_find_contact, loops_update_contact, loops_send_event, et loops_list_mailing_lists directement connectés à l’espace d’équipe Loops (“AmCloud”).
2.3. Pipeline Asynchrone Edge via Cloudflare Queues1/2
Pour découpler la réception du formulaire du traitement tiers, nous étendons le flux éprouvé du formulaire de contact :
- Frontend (
amn-blog) : Le formulaire du prefooter envoie un payload{ type: "newsletter", email: "..." }vers/api/submit. - Relais Edge (
/api/submit.ts) : Achemine la requête via Service Binding interne vers le Workerform-handler. - Producteur (
form-handler) : Valide le schéma Zod (union discriminéecontactvsnewsletter) et publie immédiatement le message dans la fileSUBMISSIONS_QUEUE. Réponse immédiate{ success: true, id: "..." }envoyée au navigateur.
2.3. Pipeline Asynchrone Edge via Cloudflare Queues2/2
- Consommateur (
submission-processor) :- Appelle l’API Loops (
POST https://app.loops.so/api/v1/contacts/create). - Enregistre une trace dans Sanity (
_type: "submission",formType: "newsletter", statutprocessed). - En cas d’erreur transitoire (ex: rate limit HTTP 429 ou erreur 5xx), le message est renvoyé en file avec retry exponentiel automatique.
- Appelle l’API Loops (
2.4. Couche Contenu Sanity (amn-studio)
- Le document singleton
prefooterSettingsconserve la maîtrise éditoriale des textes du formulaire (newsletterTitle,newsletterDescription,newsletterPlaceholder,newsletterButtonLabel) et est complété par les messages d’état (newsletterSuccessMessage,newsletterErrorMessage). - Le schéma
submissionde Sanity est mis à jour pour accepterformType(contactounewsletter) et rendrenameetmessageoptionnels lorsque le type estnewsletter.
3. Justification du Choix
| Critère | Approche Retenue (Queue L3 + Loops + Sanity) | Appel Direct Loops depuis Astro |
|---|---|---|
| Latence perçue | < 50 ms (injection mémoire dans Cloudflare Queue) | 300 - 900 ms (dépend du temps de réponse API Loops) |
| Résilience | Maximale : retry automatique en tâche de fond en cas d’incident réseau | Faible : échec visible pour l’internaute en cas de timeout Loops |
| Sécurité | Clé API Loops confinée dans les secrets Workers Cloudflare L3 | Risque de fuite si partagé avec le runtime frontend |
| Audit & RGPD | Double enregistrement (Loops + historique d’audit centralisé dans Sanity) | Enregistrement unique chez le tiers |
| Cohérence d’architecture | Aligné à 100% avec le pattern L1 + L2 + L3 du projet AMN | Brèche architecturale ad-hoc |
4. Conséquences de la Décision
Effets Positifs
- Expérience utilisateur optimale : La souscription est immédiate et non bloquante.
- Sécurité renforcée : Les clés API sensibles (
LOOPS_API_KEY,SANITY_API_WRITE_TOKEN) résident uniquement dans l’environnement du consommateur backendsubmission-processor. - Traçabilité totale : Les soumissions sont visibles dans Sanity Studio pour le monitoring éditorial.
- Support Local & Prod : En local, l’endpoint
/test-directpermet de tester la chaîne sans nécessiter de wrangler queue locale complexe.
Effets Négatifs / Points d’Attention
- Traitement en différé : Le contact apparaît dans Loops quelques secondes après la soumission du formulaire (comportement normal et sans incidence pour une newsletter).
- Gestion des doublons : Loops gère nativement les doublons d’email (mise à jour du contact existant sans erreur bloquante).
5. Alternatives Exclues
- Appel direct de Loops depuis le navigateur : Exclu car expose publiquement la clé API privée Loops.
- Appel synchrone de Loops dans
/api/submit.ts: Exclu car viole la règle de non-blocage de l’Edge Astro et empêche le retry automatique en cas de panne de Loops. - Serveur MCP Loops via URL HTTP standard sans proxy OAuth : Exclu car
https://mcp.loops.son’accepte pas les clés API d’équipe.