ADR: Intégration de la Newsletter avec Loops, Cloudflare Queues et Sanity
- 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ématique
Section titled “1. Contexte et Problématique”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é.
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 :
Section titled “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
Section titled “2. Décisions Architecturales”2.1. Plateforme d’Emailing : Loops.so (Plan Free)
Section titled “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)
Section titled “2.2. Configuration du Serveur MCP Loops (Résolution Technique)”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é :
{ "mcpServers": { "loops": { "command": "npx", "args": ["-y", "loops-mcp-server"], "env": { "LOOPS_API_KEY": "796e3ae3c6da58a59e14787256ce0507" } } }}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 Queues
Section titled “2.3. Pipeline Asynchrone Edge via Cloudflare Queues”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. - 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)
Section titled “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
Section titled “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
Section titled “4. Conséquences de la Décision”Effets Positifs
Section titled “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
Section titled “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
Section titled “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.