Type de ressource : Layout Astro (Gabarit de page)
Fichier source :src/layouts/BlogPost.astro
Statut : Actif
1. Vue d’overview
Section titled “1. Vue d’overview”1.1. Description
Section titled “1.1. Description”Layout pour les articles de blog. Fournit la structure HTML complète pour les pages d’articles, incluant l’en-tête, l’image héro, la date de publication, la date de mise à jour, et le contenu de l’article.
1.2. Objectif
Section titled “1.2. Objectif”- Fournir une structure cohérente pour tous les articles de blog
- Afficher les métadonnées de l’article (titre, dates, image)
- Intégrer les composants globaux (Header, Footer)
- Optimiser le rendu des images via Astro Assets
1.3. Périmètre concerné
Section titled “1.3. Périmètre concerné”- Type de pages : Blog (articles individuels)
- Mode de rendu : SSG (via Astro content collections)
- Consommateurs :
src/pages/blog/[...slug].astro
2. Architecture et structure
Section titled “2. Architecture et structure”2.1. Diagramme de flux
Section titled “2.1. Diagramme de flux”[Page Astro (blog/[...slug].astro)] │ (import du layout) ▼[BlogPost Layout] │ • Structure HTML complète │ • Injection des métadonnées SEO (via BaseHead) │ • Inclusion des composants globaux (Header, Footer) │ • Affichage de l'image héro │ • Affichage des dates (pubDate, updatedDate) │ • Gestion du slot de contenu ▼[HTML final]2.2. Composants impliqués
Section titled “2.2. Composants impliqués”| Composant | Rôle | Fichier |
|---|---|---|
| BaseHead | Métadonnées SEO globales | src/components/BaseHead.astro |
| Header | Navigation globale | src/components/Header.astro |
| Footer | Pied de page global | src/components/Footer.astro |
| FormattedDate | Formatage des dates | src/components/FormattedDate.astro |
| Slot de contenu | Zone de contenu dynamique | <slot /> |
3. Implémentation
Section titled “3. Implémentation”3.1. Code du layout
Section titled “3.1. Code du layout”---import { Image } from 'astro:assets';import type { CollectionEntry } from 'astro:content';import BaseHead from '../components/BaseHead.astro';import Footer from '../components/Footer.astro';import FormattedDate from '../components/FormattedDate.astro';import Header from '../components/Header.astro';
type Props = CollectionEntry<'blog'>['data'];
const { title, description, pubDate, updatedDate, heroImage } = Astro.props;---
<html lang="en"> <head> <BaseHead title={title} description={description} /> <style> main { width: calc(100% - 2em); max-width: 100%; margin: 0; } .hero-image { width: 100%; } .hero-image img { display: block; margin: 0 auto; border-radius: 12px; box-shadow: var(--box-shadow); } .prose { width: 720px; max-width: calc(100% - 2em); margin: auto; padding: 1em; color: rgb(var(--gray-dark)); } .title { margin-bottom: 1em; padding: 1em 0; text-align: center; line-height: 1; } .title h1 { margin: 0 0 0.5em 0; } .date { margin-bottom: 0.5em; color: rgb(var(--gray)); } .last-updated-on { font-style: italic; } </style> </head>
<body> <Header /> <main> <article> <div class="hero-image"> {heroImage && <Image width={1020} height={510} src={heroImage} alt="" />} </div> <div class="prose"> <div class="title"> <div class="date"> <FormattedDate date={pubDate} /> { updatedDate && ( <div class="last-updated-on"> Last updated on <FormattedDate date={updatedDate} /> </div> ) } </div> <h1>{title}</h1> <hr /> </div> <slot /> </div> </article> </main> <Footer /> </body></html>3.2. Utilisation dans une page
Section titled “3.2. Utilisation dans une page”---import BlogPost from '../../layouts/BlogPost.astro';import { getCollection } from 'astro:content';
export async function getStaticPaths() { const posts = await getCollection('blog'); return posts.map((post) => ({ params: { slug: post.slug }, props: { post }, }));}
const { post } = Astro.props;const { Content } = await post.render();---
<BlogPost {...post.data}> <Content /></BlogPost>4. Props et interface
Section titled “4. Props et interface”4.1. Props obligatoires
Section titled “4.1. Props obligatoires”| Prop | Type | Description | Exemple |
|---|---|---|---|
title |
string |
Titre de l’article | "Mon article de blog" |
pubDate |
Date |
Date de publication | new Date('2024-01-15') |
4.2. Props optionnelles
Section titled “4.2. Props optionnelles”| Prop | Type | Description | Valeur par défaut |
|---|---|---|---|
description |
string |
Meta description | undefined |
updatedDate |
Date |
Date de mise à jour | undefined |
heroImage |
ImageMetadata |
Image héro de l’article | undefined |
4.3. Slots
Section titled “4.3. Slots”| Slot | Description | Obligatoire |
|---|---|---|
default |
Contenu principal de l’article | ✅ |
5. SEO et métadonnées
Section titled “5. SEO et métadonnées”5.1. Balises meta injectées
Section titled “5.1. Balises meta injectées”| Balise | Source | Fallback |
|---|---|---|
<title> |
props.title |
- |
<meta name="description"> |
props.description |
- |
| Meta tags globaux | BaseHead |
- |
5.2. Structured Data (JSON-LD)
Section titled “5.2. Structured Data (JSON-LD)”Non implémenté - ce layout n’injecte pas de JSON-LD.
5.3. Règles de fallback
Section titled “5.3. Règles de fallback”- ✅
titleest toujours obligatoire - ✅
pubDateest toujours obligatoire - ✅
heroImageest optionnel (affichage conditionnel) - ✅
updatedDateest optionnel (affichage conditionnel)
6. Accessibilité (a11y)
Section titled “6. Accessibilité (a11y)”6.1. Structure sémantique
Section titled “6.1. Structure sémantique”<body> <Header />
<main> <article> <div class="hero-image"> <Image /> </div> <div class="prose"> <div class="title"> <time> <FormattedDate /> </time> <h1>{title}</h1> </div> <slot /> </div> </article> </main>
<Footer /></body>6.2. Règles d’accessibilité
Section titled “6.2. Règles d’accessibilité”- ✅ Structure HTML sémantique (
<header>,<main>,<article>,<footer>) - ✅ Attribut
lang="en"sur<html> - ⚠️ Pas de skip link vers le contenu principal
- ⚠️ Attribut
altvide pour l’image héro (à corriger) - ⚠️ Focus visible non testé
- ⚠️ Contraste WCAG AA non testé
7. Styles et design system
Section titled “7. Styles et design system”7.1. Utilisation des design tokens
Section titled “7.1. Utilisation des design tokens”/* Le layout utilise des variables CSS personnalisées */.prose { color: rgb(var(--gray-dark));}
.hero-image img { box-shadow: var(--box-shadow);}7.2. Responsive design
Section titled “7.2. Responsive design”/* Responsive par défaut */main { width: calc(100% - 2em); max-width: 100%;}
.prose { width: 720px; max-width: calc(100% - 2em);}7.3. Mode sombre
Section titled “7.3. Mode sombre”Non implémenté - le layout utilise les couleurs par défaut.
8. Composants globaux inclus
Section titled “8. Composants globaux inclus”8.1. Header
Section titled “8.1. Header”| Composant | Rôle | Hydratation |
|---|---|---|
Header.astro |
Navigation globale, logo, menu | Aucune |
8.2. Footer
Section titled “8.2. Footer”| Composant | Rôle | Hydratation |
|---|---|---|
Footer.astro |
Liens, copyright, réseaux sociaux | Aucune |
8.3. Autres composants globaux
Section titled “8.3. Autres composants globaux”| Composant | Rôle | Hydratation |
|---|---|---|
BaseHead.astro |
Métadonnées SEO globales | Aucune |
FormattedDate.astro |
Formatage des dates | Aucune |
9. Intégration avec les pages
Section titled “9. Intégration avec les pages”9.1. Utilisation dans une page SSG
Section titled “9.1. Utilisation dans une page SSG”---import BlogPost from '../../layouts/BlogPost.astro';import { getCollection } from 'astro:content';
export async function getStaticPaths() { const posts = await getCollection('blog'); return posts.map((post) => ({ params: { slug: post.slug }, props: { post }, }));}
const { post } = Astro.props;const { Content } = await post.render();---
<BlogPost {...post.data}> <Content /></BlogPost>9.2. Pages utilisant ce layout
Section titled “9.2. Pages utilisant ce layout”| Page | Fichier | Mode |
|---|---|---|
| Blog post | src/pages/blog/[...slug].astro |
SSG |
10. Performance et optimisation
Section titled “10. Performance et optimisation”10.1. Optimisations appliquées
Section titled “10.1. Optimisations appliquées”- ✅ HTML statique par défaut (pas de JavaScript)
- ✅ Images optimisées via Astro Assets (width, height spécifiés)
- ✅ CSS scoped minimal
- ✅ Pas de JavaScript bloquant
10.2. Core Web Vitals
Section titled “10.2. Core Web Vitals”| Métrique | Objectif | Stratégie |
|---|---|---|
| LCP | < 2.5s | Images optimisées via Astro Assets |
| INP | < 200ms | Pas de JavaScript |
| CLS | < 0.1 | Dimensions explicites des images |
10.3. Cache
Section titled “10.3. Cache”| Type | Cache-Control | Rationale |
|---|---|---|
| HTML (SSG) | public, max-age=31536000, immutable |
Contenu statique |
| CSS/JS | public, max-age=31536000, immutable |
Assets versionnés |
11. Débogage et troubleshooting
Section titled “11. Débogage et troubleshooting”11.1. Problèmes courants
Section titled “11.1. Problèmes courants”| Symptôme | Cause probable | Solution |
|---|---|---|
| Layout non appliqué | Import incorrect | Vérifier le chemin d’import |
| Image non affichée | heroImage manquant | Vérifier que l’image est dans la collection |
| Dates incorrectes | Format de date invalide | Vérifier que les dates sont des objets Date valides |
| Styles cassés | Variables CSS non définies | Vérifier les variables CSS personnalisées |
11.2. Tests manuels
Section titled “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/11.3. Logs et monitoring
Section titled “11.3. Logs et monitoring”# Logs de buildnpm run build -- --verbose
# Vérification des typesnpx astro check12. Bonnes pratiques
Section titled “12. Bonnes pratiques”12.1. Architecture
Section titled “12.1. Architecture”- ✅ Centraliser la structure HTML dans le layout
- ✅ Utiliser Astro Assets pour l’optimisation des images
- ✅ Utiliser les composants globaux (Header, Footer)
- ✅ Séparer le CSS scoped du CSS global
12.2. Code
Section titled “12.2. Code”- ✅ Typer les props avec TypeScript
- ✅ Utiliser des valeurs par défaut pour les props optionnelles
- ✅ Affichage conditionnel pour les éléments optionnels (heroImage, updatedDate)
12.3. Maintenance
Section titled “12.3. Maintenance”- ✅ Mettre à jour les styles si nécessaire
- ✅ Tester l’accessibilité régulièrement
- ⚠️ Ajouter un skip link pour l’accessibilité
- ⚠️ Corriger l’attribut alt vide pour l’image héro
13. Évolutions et roadmap
Section titled “13. Évolutions et roadmap”13.1. Améliorations planifiées
Section titled “13.1. Améliorations planifiées”- Ajout d’un skip link pour l’accessibilité
- Correction de l’attribut alt pour l’image héro
- Ajout du structured data (JSON-LD) pour les articles
- Support du mode sombre
- Ajout d’un breadcrumbs automatique
13.2. Limitations connues
Section titled “13.2. Limitations connues”- ❌ Pas de skip link
- ❌ Attribut alt vide pour l’image héro
- ❌ Pas de structured data (JSON-LD)
- ❌ Pas de mode sombre
- ❌ Locale hardcodée (‘en’)
14. Ressources liées
Section titled “14. Ressources liées”- Documentation Astro : Layouts
- Documentation Astro : Astro Assets
- Documentation Astro : Content Collections
- Layouts associés : Aucun (layout indépendant)
- Composants utilisés :
src/components/BaseHead.astrosrc/components/Header.astrosrc/components/Footer.astrosrc/components/FormattedDate.astro
15. Historique des modifications
Section titled “15. Historique des modifications”| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-15 | 1.0 | Création initiale | Devin |