Contact
Contact
Documentation technique
Type de ressource : Route Astro (Page SSR avec Preview)
Fichier source :src/pages/contact.astro
Statut : Actif
1. Vue d’ensemble
1.1. Description
Page de contact avec formulaire de soumission. Supporte le mode preview pour visualiser les drafts. Le formulaire envoie les données vers l’endpoint /api/submit qui utilise le backend L3 (Cloudflare Workers).
1.2. Objectif
- Fournir un formulaire de contact fonctionnel
- Tester l’intégration L1+L2+L3 (Sanity + Astro + Cloudflare Workers)
- Supporter le mode preview
- Afficher le message AMN (test d’intégration)
1.3. Caractéristiques
| Propriété | Valeur |
|---|---|
| URL publique | /contact |
| Mode de rendu | SSR |
| Type | Page HTML |
| Méthode HTTP | GET |
| Authentification requise | Preview uniquement (cookie) |
| Cache | Non configuré |
2. Architecture et flux
[Requête utilisateur] │ ▼[Cloudflare Pages / Edge] │ • Middleware (cookie sanity-preview) ▼[Astro Route (contact.astro)] │ • Détection du mode preview (cookie) │ • Récupération du message AMN via getAmn(isPreview) │ • Rendu du formulaire ▼[Réponse HTML] │ ▼[Formulaire soumis] │ ▼[Endpoint /api/submit] │ • Validation Zod │ • Envoi vers form-handler Worker ▼[Queue Cloudflare] │ ▼[Submission-processor Worker] │ • Création du document Sanity ▼[Sanity CMS]2.2. Composants impliqués
| Composant | Rôle | Couche |
|---|---|---|
contact.astro |
Définition de la route | L2 (Astro) |
getAmn() |
Récupération du message AMN | L2 (Astro) |
/api/submit |
Endpoint de soumission | L2 (Astro) |
| Form-handler Worker | Validation et mise en queue | L3 (Cloudflare) |
| Submission-processor Worker | Création document Sanity | L3 (Cloudflare) |
3. Implémentation
3.1. Code de la route1/2
3.1. Code de la route2/2
---import { getAmn } from '../lib/sanity'
export const prerender = false
const isPreview = Astro.cookies.get('sanity-preview')?.value === 'true'const amn = await getAmn(isPreview)---
<html lang="fr"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>Contact - AMN</title> </head> <body> {isPreview && ( <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> )}
<main> <h1>Contactez-nous</h1> <p class="subtitle">Formulaire de contact - Test d'intégration L1+L2+L3</p>
{amn && ( <div class="amn-message"> <p><strong>Message AMN:</strong> {amn.message}</p> </div> )}
<form id="contact-form" class="contact-form"> <div class="form-group"> <label for="name">Nom *</label> <input type="text" id="name" name="name" required minlength="2" maxlength="100" /> </div>
<div class="form-group"> <label for="email">Email *</label> <input type="email" id="email" name="email" required /> </div>
<div class="form-group"> <label for="message">Message *</label> <textarea id="message" name="message" required minlength="10" maxlength="2000" rows="5"></textarea> </div>
<button type="submit" id="submit-btn" class="submit-btn"> Envoyer </button> </form>
<div id="form-status" class="form-status"></div> </main>
<script is:inline> const form = document.getElementById('contact-form'); form.addEventListener('submit', async (e) => { e.preventDefault();
const formData = new FormData(form); const data = { name: String(formData.get('name') ?? ''), email: String(formData.get('email') ?? ''), message: String(formData.get('message') ?? ''), };
const response = await fetch('/api/submit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), });
const result = await response.json(); // ... gestion de la réponse }); </script> </body></html>4. Données et requêtes GROQ
4.1. Requête principale
*[_type == "amn" && status == "active"][0]4.2. Requêtes secondaires
Aucune requête secondaire n’est utilisée.
4.3. Types TypeScript associés
// Type AMN (manuel, sanity-typegen non implémenté)export type Amn = { _id: string; _type: 'amn'; message: string; status: 'active' | 'inactive';};5. Paramètres et validation
5.1. Paramètres d’URL
Aucun paramètre d’URL n’est utilisé.
5.2. Query strings
Aucune query string n’est utilisée.
5.3. Gestion des erreurs
| Code HTTP | Condition | Réponse |
|---|---|---|
| 200 | Succès | Page HTML |
| 500 | Erreur Sanity (getAmn) | Page HTML avec message d’erreur |
6. Stratégie de cache
6.1. En-têtes de cache
| Mode | Cache-Control |
CDN-Cache-Control |
Rationale |
|---|---|---|---|
| SSR Preview | Non configuré | Non configuré | À configurer (no-store recommandé) |
| SSR standard | Non configuré | Non configuré | Par défaut Cloudflare |
6.2. Implémentation dans la route
Non implémenté - pas de headers de cache explicites.
7. SEO et métadonnées
7.1. Balises meta
| Balise | Source | Fallback |
|---|---|---|
<title> |
Hardcodé “Contact - AMN” | - |
<meta name="viewport"> |
Hardcodé | - |
7.2. Sitemap
- ✅ Cette route est-elle incluse dans le sitemap ? Oui
- ✅ Fréquence de mise à jour : monthly
- ✅ Priorité : 0.5
7.3. Indexation Pagefind
- ❌ Cette route est-elle indexée par Pagefind ? Non (Pagefind non configuré)
8. Composants UI utilisés
Aucun composant UI n’est utilisé (page simple avec formulaire inline).
9. Sécurité
9.1. Accès et authentification
| Condition | Comportement |
|---|---|
| Accès public | Page accessible sans authentification |
| Mode Preview | Cookie sanity-preview requis pour voir les drafts |
9.2. Validation des entrées
- ✅ Validation HTML5 (required, minlength, maxlength, type=“email”)
- ✅ Validation côté serveur via Zod (endpoint /api/submit)
9.3. En-têtes de sécurité
Non implémenté dans cette route (à configurer via Middleware Cloudflare).
10. Débogage et troubleshooting
10.1. Problèmes courants
| Symptôme | Cause probable | Solution |
|---|---|---|
| Soumission échoue | Endpoint /api/submit inaccessible | Vérifier que le form-handler Worker est démarré |
| Erreur 500 | Token Sanity manquant | Vérifier les variables d’environnement |
| Preview non fonctionnel | Cookie manquant | Vérifier le cookie sanity-preview |
10.2. Logs et monitoring
# Logs de développementnpm run dev
# Logs du form-handler Workerwrangler tail form-handler
# Logs du submission-processor Workerwrangler tail submission-processor10.3. Tests manuels
# Test de la route en localcurl -I http://localhost:4321/contact
# Test du mode previewcurl -I -b "sanity-preview=true" http://localhost:4321/contact
# Test du formulaire# Soumettre le formulaire via l'interface web11. Bonnes pratiques
11.1. Architecture
- ✅ Détection automatique du mode preview via cookie
- ✅ Validation côté client (HTML5)
- ✅ Validation côté serveur (Zod)
- ✅ Affichage conditionnel de la bannière preview
11.2. Performance
- ✅ Script inline (
is:inline) pour éviter les charges supplémentaires - ✅ Pas de JavaScript externe
11.3. Maintenance
- ✅ Tester le flux de soumission régulièrement
- ✅ Vérifier l’intégration L1+L2+L3
12. Évolutions et roadmap
12.1. Améliorations planifiées
- Configuration des headers de cache (no-store en preview)
- Ajout de structured data (JSON-LD)
- Amélioration du design du formulaire
- Ajout de CAPTCHA pour la protection anti-spam
12.2. Limitations connues
- ❌ Pas de structured data (JSON-LD)
- ❌ Headers de cache non configurés
- ❌ Pas de protection anti-spam
- ❌ Langue hardcodée en ‘fr’
13. Ressources liées
- Documentation Astro : Routing
- Fichiers concernés :
src/pages/contact.astrosrc/pages/api/submit.tssrc/lib/sanity.ts(getAmn)services/form-handler/src/index.tsservices/submission-processor/src/index.ts
14. Historique des modifications
| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-15 | 1.0 | Création initiale | Devin |