Skip to content

Type de ressource : Route Astro (Page SSG / Page SSR / Endpoint API)
Fichier source : src/pages/[chemin].astro ou src/pages/api/[endpoint].ts
Statut : [Actif / Déprécié / En développement]

[Description concise du rîle de cette route dans l’architecture du site]

  • [Objectif principal : ex. afficher la liste des articles de blog]
  • [BĂ©nĂ©fice pour l’utilisateur final]
Propriété Valeur
URL publique /[chemin]
Mode de rendu [SSG / SSR / Hybride]
Type [Page HTML / Endpoint JSON / Redirect]
Méthode HTTP [GET / POST / Les deux]
Authentification requise [Oui / Non / Preview uniquement]
Cache [Voir §6]
[RequĂȘte utilisateur]
│
▌
[Cloudflare Pages / Edge]
│ ‱ Middleware global (CSP, cookies)
│ ‱ Routage vers Astro
▌
[Astro Route]
│ ‱ getStaticPaths (si SSG dynamique)
│ ‱ RĂ©cupĂ©ration des donnĂ©es (Sanity / local)
│ ‱ Rendu du composant
▌
[Réponse HTML / JSON]
Composant RĂŽle Couche
Fichier .astro ou .ts Définition de la route L2 (Astro)
getSanityClient() Récupération des données CMS L2 (Astro)
Composants UI Rendu visuel L2 (Astro)
Layout Structure HTML globale L2 (Astro)
Middleware Cloudflare Sécurité + Preview cookie L3 (Cloudflare)
src/pages/[chemin].astro
---
import BaseLayout from '../layouts/BaseLayout.astro';
import { getSanityClient } from '../lib/sanity';
import type { [TypeName] } from '../types/sanity';
// Configuration du rendu
export const prerender = true; // ou false pour SSR
// Génération des chemins statiques (si SSG dynamique)
export async function getStaticPaths() {
const client = getSanityClient(/* ... */);
const items = await client.fetch(`*[_type == "[type]" && status == "published"]{
slug
}`);
return items.map(item => ({
params: { slug: item.slug.current },
}));
}
// Récupération des données
const { slug } = Astro.params;
const client = getSanityClient(Astro);
const data = await client.fetch<[TypeName]>(`*[_type == "[type]" && slug.current == $slug][0]{
...,
author->{name, image},
categories[]->{title, slug}
}`, { slug });
// Gestion du 404
if (!data) {
return Astro.redirect('/404');
}
---
<BaseLayout title={data.title} description={data.seo?.metaDescription}>
<!-- Contenu de la page -->
<h1>{data.title}</h1>
<!-- ... -->
</BaseLayout>
src/pages/api/[endpoint].ts
export const prerender = false; // SSR obligatoire
export async function GET({ request, cookies, params }: APIContext) {
// Logique de l'endpoint
const data = { /* ... */ };
return new Response(JSON.stringify(data), {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=60',
},
});
}
export async function POST({ request }: APIContext) {
const body = await request.json();
// Traitement du formulaire ou de l'action
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
}
src/pages/[chemin].astro
---
export const prerender = false; // SSR pour supporter la preview
import { getSanityClient } from '../lib/sanity';
const client = getSanityClient(Astro); // Détection auto du mode preview
const data = await client.fetch(/* GROQ query */);
---
*[_type == "[type]" && slug.current == $slug][0]{
_id,
title,
slug,
publishedAt,
mainImage {
url,
metadata { dimensions, alt }
},
body,
seo {
metaTitle,
metaDescription,
ogImage
}
}
RequĂȘte Description ParamĂštres
[Nom] [Description] [ParamĂštres]
// Type généré par sanity-typegen
export type [TypeName] = {
_id: string;
_type: '[type]';
title: string;
slug: { _type: 'slug'; current: string };
// ... autres champs
};
ParamĂštre Type Obligatoire Description Validation
slug string ✅ Identifiant de la page ^[a-z0-9-]+$
[Autre] [Type] [✅/❌] [Description] [Rùgle]
ParamÚtre Type Obligatoire Description Valeur par défaut
page number ❌ Pagination 1
category string ❌ Filtre par catĂ©gorie all
Code HTTP Condition Réponse
200 SuccĂšs Page HTML / JSON
301 Slug modifié (redirect permanent) Redirection vers nouveau slug
307 Preview redirect Redirection temporaire
404 Document non trouvé Page 404 personnalisée
500 Erreur serveur (Sanity indisponible) Page d’erreur gĂ©nĂ©rique
Mode Cache-Control CDN-Cache-Control Rationale
SSG (build time) public, max-age=31536000, immutable public, max-age=31536000 Contenu statique, invalidé au rebuild
SSR standard public, max-age=60 max-age=300, stale-while-revalidate=86400 Contenu semi-dynamique
SSR Preview no-store, no-cache, must-revalidate, private no-store Contenu draft, jamais en cache
Endpoint API public, max-age=300 max-age=600 Données JSON
POST (actions) no-store no-store Jamais en cache
---
// SSG : pas besoin de headers (géré par Cloudflare Pages)
export const prerender = true;
// SSR : configuration explicite
export const prerender = false;
Astro.response.headers.set('Cache-Control', 'public, max-age=60');
Astro.response.headers.set('CDN-Cache-Control', 'max-age=300, stale-while-revalidate=86400');
// Preview : bypass total
const isPreview = Astro.cookies.get('sanity-preview')?.value === 'true';
if (isPreview) {
Astro.response.headers.set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
Astro.response.headers.set('CDN-Cache-Control', 'no-store');
}
---
Balise Source Fallback
<title> data.seo.metaTitle data.title
<meta name="description"> data.seo.metaDescription data.excerpt
<meta property="og:title"> data.seo.metaTitle data.title
<meta property="og:description"> data.seo.metaDescription data.excerpt
<meta property="og:image"> data.seo.ogImage data.mainImage
<link rel="canonical"> URL publique de la page -
  • ✅ Cette route est-elle incluse dans le sitemap ? [Oui/Non]
  • ✅ FrĂ©quence de mise Ă  jour : [daily / weekly / monthly]
  • ✅ PrioritĂ© : [0.0 Ă  1.0]
  • ✅ Cette route est-elle indexĂ©e par Pagefind ? [Oui/Non]
  • ✅ Poids du titre : [2.0]
  • ✅ Filtres applicables : [type, catĂ©gorie]
Composant Fichier RĂŽle Hydratation
BaseLayout src/layouts/BaseLayout.astro Structure HTML Aucune
HeroSection src/components/sections/HeroSection.astro Section hero Aucune
MobileNav src/components/ui/MobileNav.astro Navigation mobile client:load
[Autre] [Chemin] [RÎle] [Stratégie]
Condition Comportement
AccĂšs public Page accessible sans authentification
Mode Preview Cookie sanity-preview requis pour voir les drafts
Endpoint API sensible Validation du secret/token requise
  • ✅ Les paramĂštres d’URL sont validĂ©s (format du slug)
  • ✅ Les query strings sont sanitizĂ©es
  • ✅ Les entrĂ©es de formulaire sont validĂ©es cĂŽtĂ© serveur
  • ✅ Protection CSRF pour les endpoints POST

Injectés par le Middleware Cloudflare (voir /cloudflare/workers/middleware.md) :

  • Content-Security-Policy
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Strict-Transport-Security
SymptĂŽme Cause probable Solution
Page 404 Slug incorrect ou document non publié Vérifier le slug dans Sanity
Contenu draft en production Mode preview activé par erreur Supprimer le cookie sanity-preview
Page blanche Erreur GROQ ou type manquant Vérifier les logs de build
Cache stale CDN non invalidé Attendre le TTL ou forcer un rebuild
500 en SSR Token Sanity manquant VĂ©rifier les variables d’environnement
getStaticPaths lent RequĂȘte GROQ non optimisĂ©e Ajouter des projections explicites
Terminal window
# Logs de développement
npm run dev
# Logs de build (SSG)
npm run build -- --verbose
# Logs Cloudflare (SSR production)
wrangler pages deployment tail
# Vérification des types
npx astro check
Terminal window
# Test de la route en local
curl -I http://localhost:4321/[chemin]
# Test du mode preview
curl -I -b "sanity-preview=true" http://localhost:4321/[chemin]
# Test d'un endpoint API
curl -X POST http://localhost:4321/api/[endpoint] \
-H "Content-Type: application/json" \
-d '{"key": "value"}'
# Test de la gestion 404
curl -I http://localhost:4321/[chemin-inexistant]
# Attendu : 404 ou redirect vers /404
  • ✅ Utiliser export const prerender = true par dĂ©faut (SSG)
  • ✅ N’utiliser prerender = false que si nĂ©cessaire (preview, formulaires, API)
  • ✅ Centraliser les requĂȘtes GROQ dans src/lib/queries.ts
  • ✅ Toujours typer les donnĂ©es avec les types gĂ©nĂ©rĂ©s par sanity-typegen
  • ✅ GĂ©rer le cas 404 explicitement
  • ✅ Utiliser getStaticPaths pour prĂ©-gĂ©nĂ©rer les pages dynamiques en SSG
  • ✅ Limiter les projections GROQ aux champs nĂ©cessaires
  • ✅ Utiliser loading="lazy" pour les images non-LCP
  • ✅ Éviter les composants hydratĂ©s sauf si interaction requise
  • ✅ Documenter les changements de route dans ce fichier
  • ✅ Mettre Ă  jour le sitemap lors de l’ajout/suppression de routes
  • ✅ Tester les routes en staging avant production
  • ✅ VĂ©rifier les redirects lors de la modification de slugs
  • [Évolution 1 : ex. Pagination pour les listings]
  • [Évolution 2 : ex. Support i18n (routes localisĂ©es)]
  • [Évolution 3 : ex. View Transitions Astro]
  • ❌ Les pages SSG ne supportent pas le mode Preview
  • ❌ getStaticPaths est exĂ©cutĂ© uniquement au build (pas de mise Ă  jour en temps rĂ©el)
  • ❌ Les Pages Functions SSR ont une limite de 128 MB de mĂ©moire
  • Documentation Astro : Routing
  • Documentation Astro : getStaticPaths
  • Documentation Astro : Endpoints
  • DAT L2 : §3 - Structure des Routes et StratĂ©gie de Rendu
  • DAT L2 : §5 - IntĂ©gration Sanity dans Astro
  • DAT L3 : §3 - Middleware Global
  • Routes associĂ©es :
    • [Liste des routes liĂ©es ou dĂ©pendantes]
  • Fichiers concernĂ©s :
    • src/pages/[chemin].astro
    • src/lib/queries.ts
    • src/layouts/BaseLayout.astro
Date Version Description Auteur
YYYY-MM-DD 1.0 Création initiale [Nom]
YYYY-MM-DD 1.1 [Modification] [Nom]
---
**Points clés de ce template :**
- Couvre les trois types de routes Astro (page SSG, page SSR, endpoint API)
- Détaille la stratégie de cache par mode de rendu
- Inclut la gestion du mode Preview au niveau de la route
- Documente le SEO, l'indexation Pagefind et le sitemap
- Fournit les variantes de code pour chaque type de route
- Inclut la gestion des erreurs et des codes HTTP
- Sépare clairement les paramÚtres d'URL, les query strings et la validation
Edit page

Last updated: