Spécification : Middleware Astro Preview
Slice : Slice 1 (Page d’accueil)
Cycle : DOC → SPEC → CODE → TEST → INTÉG
Statut : SPEC
1. Objectif
Section titled “1. Objectif”Implémenter un middleware Astro pour détecter le mode preview et injecter une bannière d’information dans toutes les pages (prerendered et SSR), permettant aux collaborateurs de savoir qu’ils sont en mode preview et de quitter ce mode facilement.
2. Configuration technique
Section titled “2. Configuration technique”2.1. Middleware Astro
Section titled “2.1. Middleware Astro”Fichier : apps/web/src/middleware.ts
Configuration :
- TypeScript
- Exécution côté serveur
- Accès aux cookies de la requête
- Modification de la réponse HTML
2.2. Pattern d’injection
Section titled “2.2. Pattern d’injection”Injection de bannière :
- Détecter la balise
<body>dans le HTML - Insérer la bannière après
<body> - Ne pas modifier le reste du HTML
HTML de la bannière :
<div class="preview-banner"> ⚠️ <strong>Mode Preview Activé</strong> — Visualisation des brouillons Sanity non publiés (Drafts). <a href="/api/exit-preview" class="exit-link">Quitter la preview</a></div>3. Structure des fichiers
Section titled “3. Structure des fichiers”3.1. Middleware
Section titled “3.1. Middleware”Fichier : apps/web/src/middleware.ts
Structure :
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware((context, next) => { // Détection cookie et injection bannière});3.2. Styles
Section titled “3.2. Styles”Options :
- Styles inline dans la bannière
- Ou fichier CSS séparé importé
4. Implémentation du middleware
Section titled “4. Implémentation du middleware”4.1. Détection du cookie
Section titled “4.1. Détection du cookie”Logique :
const isPreview = context.cookies.get('sanity-preview')?.value === 'true';4.2. Gestion de route exit-preview
Section titled “4.2. Gestion de route exit-preview”Logique :
if (context.url.pathname === '/api/exit-preview') { const response = new Response(null, { status: 307, headers: { 'Location': '/', 'Set-Cookie': 'sanity-preview=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0' } }); return response;}4.3. Injection de bannière
Section titled “4.3. Injection de bannière”Logique :
if (isPreview) { const response = await next(); const html = await response.text(); const modifiedHtml = html.replace( '<body>', '<body>' + previewBannerHtml ); return new Response(modifiedHtml, { headers: response.headers });}5. Comportement attendu
Section titled “5. Comportement attendu”5.1. Pages prerendered (SSG)
Section titled “5.1. Pages prerendered (SSG)”Comportement :
- Le middleware détecte le cookie (contrairement aux composants)
- La bannière est injectée dans le HTML statique
- Respecte l’ADR-SSR-Pur.md (index.astro reste prerendered)
5.2. Pages SSR
Section titled “5.2. Pages SSR”Comportement :
- Le middleware détecte le cookie
- La bannière est injectée dans le HTML généré
- Cohérence avec les pages prerendered
5.3. Route exit-preview
Section titled “5.3. Route exit-preview”Comportement :
- Middleware intercepte
/api/exit-preview - Supprime le cookie
sanity-preview - Redirect vers
/ - Code HTTP 307
6. Tests et validation
Section titled “6. Tests et validation”6.1. Tests de middleware
Section titled “6.1. Tests de middleware”Scénarios :
- Sans cookie preview : Page s’affiche normalement sans bannière
- Avec cookie preview : Bannière injectée après
<body> - Route exit-preview : Cookie supprimé et redirect vers
/ - Page prerendered : Bannière injectée dans HTML statique
- Page SSR : Bannière injectée dans HTML généré
6.2. Commandes de test
Section titled “6.2. Commandes de test”Commandes :
task build:webtask devTests manuels :
- Tester index.astro avec cookie preview
- Tester [slug].astro avec cookie preview
- Tester la route
/api/exit-preview
7. Intégration avec l’existant
Section titled “7. Intégration avec l’existant”7.1. Compatibilité avec index.astro
Section titled “7.1. Compatibilité avec index.astro”État actuel :
- index.astro est prerendered (
export const prerender = true) - Ne peut pas détecter les cookies dans le composant
- Le middleware détectera le cookie et injectera la bannière
Modification requise :
- Retirer la logique de bannière preview de index.astro (déjà fait)
- Garder le mode prerendered
7.2. Compatibilité avec [slug].astro
Section titled “7.2. Compatibilité avec [slug].astro”État actuel :
- [slug].astro est SSR (
export const prerender = false) - Détecte déjà le cookie dans le composant
- Affiche déjà la bannière preview
Modification requise :
- Garder la logique existante (cohérence)
- Le middleware injectera aussi la bannière (non problématique)
7.3. Compatibilité avec welcome.astro
Section titled “7.3. Compatibilité avec welcome.astro”État actuel :
- welcome.astro est SSR
- Détecte le cookie et affiche la bannière
Modification requise :
- Aucune modification nécessaire
- Le middleware injectera aussi la bannière (cohérence)
8. Problèmes potentiels et solutions
Section titled “8. Problèmes potentiels et solutions”8.1. Performance
Section titled “8.1. Performance”Problème : Modification du HTML à chaque requête avec cookie preview
Solution :
- Le middleware ne modifie que si cookie présent
- Impact minimal (detection cookie + replace simple)
- Cache désactivé pour les requêtes avec cookie preview
8.2. Injection HTML
Section titled “8.2. Injection HTML”Problème : Le pattern <body> peut ne pas exister ou être différent
Solution :
- Vérifier que
<body>existe avant injection - Fallback : pas de bannière si structure HTML invalide
8.3. Double bannière
Section titled “8.3. Double bannière”Problème : SSR pages affichent déjà la bannière
Solution :
- Option 1 : Retirer la logique SSR (cohérence)
- Option 2 : Garder les deux (non problématique visuellement)
- Recommandation : Retirer la logique SSR pour cohérence
9. Checklist de validation
Section titled “9. Checklist de validation”Avant de passer à l’étape CODE :
- Spécification technique complète
- Pattern d’injection défini
- Route exit-preview spécifiée
- Tests définis
- Intégration avec l’existant analysée
- Problèmes potentiels identifiés
10. Approbation
Section titled “10. Approbation”Validation requise : Confirmer que la spécification peut passer à l’étape CODE.
11. Historique des modifications
Section titled “11. Historique des modifications”| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-17 | 1.0 | Création initiale | Devin |