Skip to content

Type de ressource : Route Astro (Page SSR avec Preview)
Fichier source : src/pages/contact.astro
Statut : Actif

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).

  • 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)
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é
[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]
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)
---
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>
*[_type == "amn" && status == "active"][0]

Aucune requĂȘte secondaire n’est utilisĂ©e.

// Type AMN (manuel, sanity-typegen non implémenté)
export type Amn = {
_id: string;
_type: 'amn';
message: string;
status: 'active' | 'inactive';
};

Aucun paramĂštre d’URL n’est utilisĂ©.

Aucune query string n’est utilisĂ©e.

Code HTTP Condition Réponse
200 SuccĂšs Page HTML
500 Erreur Sanity (getAmn) Page HTML avec message d’erreur
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

Non implémenté - pas de headers de cache explicites.

Balise Source Fallback
<title> HardcodĂ© “Contact - AMN” -
<meta name="viewport"> Hardcodé -
  • ✅ Cette route est-elle incluse dans le sitemap ? Oui
  • ✅ FrĂ©quence de mise Ă  jour : monthly
  • ✅ PrioritĂ© : 0.5
  • ❌ Cette route est-elle indexĂ©e par Pagefind ? Non (Pagefind non configurĂ©)

Aucun composant UI n’est utilisĂ© (page simple avec formulaire inline).

Condition Comportement
AccĂšs public Page accessible sans authentification
Mode Preview Cookie sanity-preview requis pour voir les drafts
  • ✅ Validation HTML5 (required, minlength, maxlength, type=“email”)
  • ✅ Validation cĂŽtĂ© serveur via Zod (endpoint /api/submit)

Non implémenté dans cette route (à configurer via Middleware Cloudflare).

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
Terminal window
# Logs de développement
npm run dev
# Logs du form-handler Worker
wrangler tail form-handler
# Logs du submission-processor Worker
wrangler tail submission-processor
Terminal window
# Test de la route en local
curl -I http://localhost:4321/contact
# Test du mode preview
curl -I -b "sanity-preview=true" http://localhost:4321/contact
# Test du formulaire
# Soumettre le formulaire via l'interface web
  • ✅ 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
  • ✅ Script inline (is:inline) pour Ă©viter les charges supplĂ©mentaires
  • ✅ Pas de JavaScript externe
  • ✅ Tester le flux de soumission rĂ©guliĂšrement
  • ✅ VĂ©rifier l’intĂ©gration L1+L2+L3
  • 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
  • ❌ Pas de structured data (JSON-LD)
  • ❌ Headers de cache non configurĂ©s
  • ❌ Pas de protection anti-spam
  • ❌ Langue hardcodĂ©e en ‘fr’
  • Documentation Astro : Routing
  • Fichiers concernĂ©s :
    • src/pages/contact.astro
    • src/pages/api/submit.ts
    • src/lib/sanity.ts (getAmn)
    • services/form-handler/src/index.ts
    • services/submission-processor/src/index.ts
Date Version Description Auteur
2026-09-15 1.0 Création initiale Devin
Edit page

Last updated: