SPEC — Correction Composant 2 : Blog Listing + Typage
Cycle : DOC → SPEC → CODE → TEST
Scope : 3 corrections ciblées, sans refonte complète
Statut : En attente d’approbation avant CODE
1. Problème 1 — blog/index.astro ne lit pas depuis Sanity [BLOQUANT]
Section titled “1. Problème 1 — blog/index.astro ne lit pas depuis Sanity [BLOQUANT]”1.1 Situation actuelle
Section titled “1.1 Situation actuelle”// blog/index.astro — ACTUEL (INCORRECT)const posts = (await getCollection('blog')).sort(...)// → Lit des fichiers Markdown locaux, pas Sanity1.2 Correction ciblée
Section titled “1.2 Correction ciblée”Fichier : apps/web/src/pages/blog/index.astro
Changements :
- Remplacer
getCollection('blog')parloadQuery()avec GROQ - Conserver
export const prerender = false(SSR — même raison queindex.astro: accès cookies pour Visual Editing) - Garder le même template HTML (juste changer la source de données)
- Utiliser
MainLayoutà la place du layout inline actuel (cohérence avec le reste)
Query GROQ (triée par publishedAt desc, même ordre que le tri actuel par date) :
*[_type == "post"] | order(publishedAt desc) { _id, _type, title, slug, publishedAt, mainImage { asset->{ _id, url, metadata { lqip, dimensions } }, alt }, author->{ _id, name }, categories[]->{ _id, title }}Type de retour : PostListItem[] (type local défini dans le fichier)
2. Problème 2 — Typage as any dans blog/[slug].astro [NON BLOQUANT]
Section titled “2. Problème 2 — Typage as any dans blog/[slug].astro [NON BLOQUANT]”2.1 Situation actuelle
Section titled “2.1 Situation actuelle”// blog/[slug].astro — ACTUEL (INCORRECT)const { data: post } = await loadQuery({...})// → post est `unknown`, tout casté `as any`2.2 Correction ciblée
Section titled “2.2 Correction ciblée”Fichier : apps/web/src/pages/blog/[slug].astro
Changements :
- Définir un type local
SanityPostqui reflète exactement la projection GROQ existante - Passer le type générique à
loadQuery<SanityPost>({...}) - Remplacer les
(post as any)?.xparpost?.x - Pas de changement fonctionnel — uniquement typage
Note : On n’importe pas Post depuis apps/studio/sanity.types.ts car le type brut ne correspond pas à la projection GROQ (les références sont résolues via -> dans la query). On définit un type local correspondant exactement à la projection.
3. Problème 3 — SEO description = titre [NON BLOQUANT]
Section titled “3. Problème 3 — SEO description = titre [NON BLOQUANT]”3.1 Situation actuelle
Section titled “3.1 Situation actuelle”// blog/[slug].astro ligne 142 — ACTUEL (INCORRECT)description={(post as any)?.title || contentPost?.data.title}// → description SEO = titre de l'article3.2 Correction ciblée
Section titled “3.2 Correction ciblée”Fichier : apps/web/src/pages/blog/[slug].astro
Changements :
- Ajouter un champ
excerpt(string, optionnel) au schéma Sanitypost.ts - Ajouter
excerptà la query GROQ de[slug].astro - Utiliser
post?.excerptcomme description, fallback sur le titre - Régénérer
sanity.types.tsavectask typegen(si disponible) ou manuellement
Schéma Sanity (apps/studio/schemaTypes/post.ts) :
defineField({ name: 'excerpt', title: 'Excerpt', type: 'text', rows: 3, description: 'Short description for SEO and listing previews',}),4. Ordre d’implémentation
Section titled “4. Ordre d’implémentation”- Problème 3d (schéma Sanity
excerpt) — d’abord car ça touche le studio - Problème 1 (
blog/index.astro→ Sanity) — correction principale - Problème 2 (typage
[slug].astro) — amélioration qualité
5. Ce qu’on ne touche PAS
Section titled “5. Ce qu’on ne touche PAS”loadQuery.ts— fonctionne parfaitement, pas de changementMainLayout.astro— pas de changementBlogPost.astrolayout — conservé pour le fallback content collections- Le fallback content collections dans
[slug].astro— conservé (utile en dev) astro.config.mjs— pas de changement
6. Critères de validation (TEST)
Section titled “6. Critères de validation (TEST)”-
curl http://localhost:4321/blog/liste les posts Sanity (pas les Markdown) - Les posts Sanity ont titre, date, auteur, image visible dans le listing
-
curl http://localhost:4321/blog/<slug-sanity>affiche l’article complet - La
<meta name="description">contient l’excerpt, pas le titre -
task typecheck→ 0 erreurs - Pas de régression sur les posts Markdown (fallback dans
[slug].astro)