Skip to content

[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

src/layouts/[NomLayout].astro
---
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

src/layouts/BlogLayout.astro
---
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

src/layouts/BaseLayout.astro
---
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 + SearchAction
  • Article / BlogPosting
  • CreativeWork / Project

5.3. Règles de fallback

  • ✅ title est toujours obligatoire
  • ✅ description utilise un fallback intelligent depuis les données Sanity si disponible
  • ✅ ogImage utilise l’image principale du contenu si non spécifiée
  • ✅ canonical est 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
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

src/pages/blog/[slug].astro
---
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

src/pages/contact.astro
---
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

Terminal window
# Test local
npm run dev
# Vérification de l'accessibilité
npx axe http://localhost:4321/
# Vérification des performances
npx lighthouse http://localhost:4321/
# Validation HTML
npx html-validate src/pages/[page].astro

11.3. Logs et monitoring

Terminal window
# Logs de build
npm run build -- --verbose
# Vérification des types
npx astro check

12. 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ées1/2

  • Documentation Astro : Layouts
  • Documentation Astro : Slots
  • DAT L2 : §3 - Structure de l’Espace de Travail
  • DAT L2 : §10 - Stratégie SEO
  • DAT L2 : §11 - Accessibilité
  • DAT L2 : §12 - Design System

14. Ressources liées2/2

  • Layouts associés :
    • src/layouts/BaseLayout.astro
    • src/layouts/MainLayout.astro
    • src/layouts/BlogLayout.astro
  • Composants utilisés :
    • src/components/ui/Header.astro
    • src/components/ui/Footer.astro
    • src/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
Switch to normal mode

Contents