[Nom du Layout]
[Nom du Layout]
Documentation technique
Type de ressource : Layout Astro (Gabarit de page)
Fichier source :src/layouts/[NomLayout].astro
Statut : [Actif / Déprécié / En développement]
1. Vue d’overview
1.1. Description
[Description concise du rôle de ce layout dans l’architecture du site]
1.2. Objectif
- [Objectif principal : ex. fournir la structure HTML globale pour les pages de blog]
- [Bénéfice pour l’architecture : ex. cohérence visuelle + SEO centralisé]
1.3. Périmètre concerné
- Type de pages : [Blog / Portfolio / Vitrine / Documentation / Toutes]
- Mode de rendu : [SSG / SSR / Les deux]
- Consommateurs : [Liste des pages qui utilisent ce layout]
2. Architecture et structure
2.1. Diagramme de flux
[Page Astro] │ (import du layout) ▼[Layout] │ • Structure HTML globale │ • Injection des métadonnées SEO │ • Inclusion des composants globaux (Header, Footer) │ • Gestion des slots de contenu ▼[HTML final]2.2. Composants impliqués
| Composant | Rôle | Fichier |
|---|---|---|
| Layout parent | Structure HTML de base | src/layouts/BaseLayout.astro (si applicable) |
| Header | Navigation globale | src/components/ui/Header.astro |
| Footer | Pied de page global | src/components/ui/Footer.astro |
| SEO Component | Injection des balises meta | src/components/seo/SeoJsonLd.astro |
| Slot de contenu | Zone de contenu dynamique | <slot /> |
3. Implémentation
3.1. Code du layout1/2
3.1. Code du layout2/2
---import BaseLayout from './BaseLayout.astro';import Header from '../components/ui/Header.astro';import Footer from '../components/ui/Footer.astro';import SeoJsonLd from '../components/seo/SeoJsonLd.astro';
interface Props { title: string; description?: string; ogImage?: string; canonical?: string; jsonLd?: object;}
const { title, description, ogImage, canonical = Astro.url.href, jsonLd} = Astro.props;---
<BaseLayout title={title} description={description} ogImage={ogImage} canonical={canonical}> <Header />
<main id="main-content"> <slot /> </main>
<Footer />
{jsonLd && <SeoJsonLd data={jsonLd} />}</BaseLayout>3.2. Variante : Layout avec sidebar1/2
3.2. Variante : Layout avec sidebar2/2
---import BaseLayout from './BaseLayout.astro';import Header from '../components/ui/Header.astro';import Footer from '../components/ui/Footer.astro';import Sidebar from '../components/ui/BlogSidebar.astro';
interface Props { title: string; description?: string; publishedAt?: string; author?: { name: string; image?: string; };}
const { title, description, publishedAt, author } = Astro.props;---
<BaseLayout title={title} description={description}> <Header />
<div class="blog-layout"> <article class="blog-content"> <header class="blog-header"> <h1>{title}</h1> {publishedAt && ( <time datetime={publishedAt}> {new Date(publishedAt).toLocaleDateString('fr-FR')} </time> )} {author && ( <div class="author"> {author.image && <img src={author.image} alt={author.name} />} <span>{author.name}</span> </div> )} </header>
<slot /> </article>
<Sidebar /> </div>
<Footer /></BaseLayout>
<style> .blog-layout { display: grid; grid-template-columns: 1fr 300px; gap: 2rem; max-width: 1200px; margin: 0 auto; padding: 2rem; }
@media (max-width: 768px) { .blog-layout { grid-template-columns: 1fr; } }</style>3.3. Variante : Layout Base (structure minimale)1/2
3.3. Variante : Layout Base (structure minimale)2/2
---interface Props { title: string; description?: string; ogImage?: string; canonical?: string;}
const { title, description, ogImage = '/images/default-og.jpg', canonical = Astro.url.href} = Astro.props;---
<!DOCTYPE html><html lang="fr"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="generator" content={Astro.generator} />
<!-- SEO Meta Tags --> <title>{title}</title> {description && <meta name="description" content={description} />} <link rel="canonical" href={canonical} />
<!-- Open Graph --> <meta property="og:type" content="website" /> <meta property="og:title" content={title} /> {description && <meta property="og:description" content={description} />} <meta property="og:image" content={ogImage} /> <meta property="og:url" content={canonical} />
<!-- Twitter Card --> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content={title} /> {description && <meta name="twitter:description" content={description} />} <meta name="twitter:image" content={ogImage} />
<!-- Favicon --> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<!-- Styles --> <link rel="stylesheet" href="/styles/global.css" />
<!-- Analytics (si applicable) --> <!-- Cloudflare Web Analytics ou autre --> </head> <body> <slot /> </body></html>4. Props et interface
4.1. Props obligatoires
| Prop | Type | Description | Exemple |
|---|---|---|---|
title |
string |
Titre de la page (utilisé pour <title> et OG) |
"Mon article de blog" |
4.2. Props optionnelles
| Prop | Type | Description | Valeur par défaut |
|---|---|---|---|
description |
string |
Meta description | undefined |
ogImage |
string |
URL de l’image Open Graph | '/images/default-og.jpg' |
canonical |
string |
URL canonique | Astro.url.href |
jsonLd |
object |
Données JSON-LD pour le structured data | undefined |
| [Autre prop] | [Type] | [Description] | [Valeur] |
4.3. Slots
| Slot | Description | Obligatoire |
|---|---|---|
default |
Contenu principal de la page | ✅ |
sidebar |
Contenu de la sidebar (si applicable) | ❌ |
head |
Contenu supplémentaire dans <head> |
❌ |
5. SEO et métadonnées
5.1. Balises meta injectées
| Balise | Source | Fallback |
|---|---|---|
<title> |
props.title |
- |
<meta name="description"> |
props.description |
- |
<link rel="canonical"> |
props.canonical |
Astro.url.href |
<meta property="og:title"> |
props.title |
- |
<meta property="og:description"> |
props.description |
- |
<meta property="og:image"> |
props.ogImage |
Image par défaut |
<meta property="og:url"> |
props.canonical |
Astro.url.href |
5.2. Structured Data (JSON-LD)
{jsonLd && ( <script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />)}Types de JSON-LD supportés :
Organization(global)WebSite+SearchActionArticle/BlogPostingCreativeWork/Project
5.3. Règles de fallback
- ✅
titleest toujours obligatoire - ✅
descriptionutilise un fallback intelligent depuis les données Sanity si disponible - ✅
ogImageutilise l’image principale du contenu si non spécifiée - ✅
canonicalest toujours généré automatiquement
6. Accessibilité (a11y)
6.1. Structure sémantique
<body> <a href="#main-content" class="skip-link">Aller au contenu principal</a>
<Header />
<main id="main-content"> <slot /> </main>
<Footer /></body>6.2. Règles d’accessibilité
- ✅ Skip link vers le contenu principal
- ✅ Structure HTML sémantique (
<header>,<main>,<footer>,<article>) - ✅ Attribut
lang="fr"sur<html> - ✅ Focus visible sur tous les éléments interactifs
- ✅ Contraste WCAG AA minimum
- ✅ Navigation clavier complète
7. Styles et design system
7.1. Utilisation des design tokens
/* Le layout utilise les design tokens définis dans tokens.css */.blog-layout { max-width: var(--container-max-width, 1200px); margin: 0 auto; padding: var(--spacing-lg, 2rem); font-family: var(--font-family-base); color: var(--color-text-primary); background-color: var(--color-bg-primary);}7.2. Responsive design
/* Mobile-first approach */.blog-layout { display: grid; grid-template-columns: 1fr; gap: var(--spacing-md, 1rem);}
/* Tablet */@media (min-width: 768px) { .blog-layout { grid-template-columns: 1fr 300px; gap: var(--spacing-lg, 2rem); }}
/* Desktop */@media (min-width: 1024px) { .blog-layout { max-width: var(--container-max-width, 1200px); }}7.3. Mode sombre (si applicable)
/* Support du mode sombre via prefers-color-scheme */@media (prefers-color-scheme: dark) { :root { --color-bg-primary: var(--color-gray-9); --color-text-primary: var(--color-gray-1); }}
/* Ou via classe manuelle */[data-theme="dark"] { --color-bg-primary: var(--color-gray-9); --color-text-primary: var(--color-gray-1);}8. Composants globaux inclus
8.1. Header
| Composant | Rôle | Hydratation |
|---|---|---|
Header.astro |
Navigation globale, logo, menu | Aucune |
MobileNav.astro |
Menu mobile interactif | client:load |
8.2. Footer
| Composant | Rôle | Hydratation |
|---|---|---|
Footer.astro |
Liens, copyright, réseaux sociaux | Aucune |
8.3. Autres composants globaux
| Composant | Rôle | Hydratation |
|---|---|---|
SeoJsonLd.astro |
Injection du structured data | Aucune |
Analytics.astro |
Scripts analytics (si applicable) | client:load |
| [Autre] | [Rôle] | [Stratégie] |
9. Intégration avec les pages
9.1. Utilisation dans une page SSG
---import BlogLayout from '../../layouts/BlogLayout.astro';import { getSanityClient } from '../../lib/sanity';
export async function getStaticPaths() { // ... génération des chemins}
const { slug } = Astro.params;const post = await getSanityClient(Astro).fetch(/* ... */);---
<BlogLayout title={post.title} description={post.excerpt} publishedAt={post.publishedAt} author={post.author}> <!-- Contenu de l'article --></BlogLayout>9.2. Utilisation dans une page SSR
---import MainLayout from '../layouts/MainLayout.astro';
export const prerender = false;
// Logique SSR...---
<MainLayout title="Contact" description="Formulaire de contact"> <!-- Contenu de la page --></MainLayout>9.3. Pages utilisant ce layout
| Page | Fichier | Mode |
|---|---|---|
| [Nom de la page] | src/pages/[chemin].astro |
[SSG/SSR] |
| [Autre page] | src/pages/[chemin].astro |
[SSG/SSR] |
10. Performance et optimisation
10.1. Optimisations appliquées
- ✅ HTML statique par défaut (pas de JavaScript sauf si nécessaire)
- ✅ Images optimisées (WebP/AVIF via Cloudflare)
- ✅ CSS minimal et critique inline (si applicable)
- ✅ Fonts préchargées (si applicable)
- ✅ Pas de JavaScript bloquant sur le chemin critique
10.2. Core Web Vitals
| Métrique | Objectif | Stratégie |
|---|---|---|
| LCP | < 2.5s | Images optimisées, fonts préchargées |
| INP | < 200ms | JavaScript minimal, îlots ciblés |
| CLS | < 0.1 | Dimensions explicites, fonts stables |
10.3. Cache
| Type | Cache-Control | Rationale |
|---|---|---|
| HTML (SSG) | public, max-age=31536000, immutable |
Contenu statique |
| HTML (SSR) | public, max-age=60 |
Contenu semi-dynamique |
| CSS/JS | public, max-age=31536000, immutable |
Assets versionnés |
11. Débogage et troubleshooting
11.1. Problèmes courants
| Symptôme | Cause probable | Solution |
|---|---|---|
| Layout non appliqué | Import incorrect | Vérifier le chemin d’import |
| SEO manquant | Props non passées | Vérifier les props obligatoires |
| Styles cassés | Conflit CSS | Vérifier les spécificités et l’ordre |
| Accessibilité dégradée | Structure HTML incorrecte | Valider avec axe-core |
| Performance dégradée | JavaScript inutile | Vérifier les hydratations |
11.2. Tests manuels
# Test localnpm run dev
# Vérification de l'accessibiliténpx axe http://localhost:4321/
# Vérification des performancesnpx lighthouse http://localhost:4321/
# Validation HTMLnpx html-validate src/pages/[page].astro11.3. Logs et monitoring
# Logs de buildnpm run build -- --verbose
# Vérification des typesnpx astro check12. Bonnes pratiques
12.1. Architecture
- ✅ Centraliser la structure HTML globale dans un
BaseLayout - ✅ Créer des layouts spécialisés pour chaque type de contenu (Blog, Portfolio, etc.)
- ✅ Utiliser des slots pour la flexibilité
- ✅ Injecter les métadonnées SEO de manière centralisée
- ✅ Respecter la structure sémantique HTML
12.2. Code
- ✅ Typer les props avec TypeScript
- ✅ Utiliser des valeurs par défaut pour les props optionnelles
- ✅ Valider les props obligatoires
- ✅ Utiliser les design tokens pour les styles
- ✅ Séparer le CSS scoped du CSS global
12.3. Maintenance
- ✅ Documenter les props et slots dans ce fichier
- ✅ Tester l’accessibilité régulièrement
- ✅ Vérifier les performances avec Lighthouse
- ✅ Mettre à jour les layouts lors des changements de design
13. Évolutions et roadmap
13.1. Améliorations planifiées
- [Évolution 1 : ex. Support du mode sombre]
- [Évolution 2 : ex. Ajout d’un breadcrumbs automatique]
- [Évolution 3 : ex. Intégration de View Transitions]
13.2. Limitations connues
- ❌ Les layouts ne peuvent pas être hydratés (pas de JavaScript côté layout)
- ❌ Les slots ne supportent pas les props (utiliser des contextes si nécessaire)
- ❌ Les layouts imbriqués peuvent compliquer la maintenance
14. Ressources liées2/2
- Layouts associés :
src/layouts/BaseLayout.astrosrc/layouts/MainLayout.astrosrc/layouts/BlogLayout.astro
- Composants utilisés :
src/components/ui/Header.astrosrc/components/ui/Footer.astrosrc/components/seo/SeoJsonLd.astro
15. Historique des modifications1/2
| Date | Version | Description | Auteur |
|---|---|---|---|
| YYYY-MM-DD | 1.0 | Création initiale | [Nom] |
| YYYY-MM-DD | 1.1 | [Modification] | [Nom] |
15. Historique des modifications2/2
---
**Points clés de ce template :**- Documente la structure HTML globale et les slots- Détaille les props et leur typage TypeScript- Inclut la gestion centralisée du SEO (meta tags, JSON-LD)- Couvre l'accessibilité (structure sémantique, skip link)- Fournit l'intégration avec le design system (tokens CSS)- Sépare clairement les layouts de base et les layouts spécialisés- Inclut les bonnes pratiques de performance et de maintenance