Skip to content

Diagnostic et plan - Découplage du contenu /blog via Sanity

Diagnostic et plan - Découplage du contenu /blog via Sanity

Diagnostic approfondi et plan de conception pour assurer que 100% du contenu éditorial de la page /blog soit piloté par Sanity CMS (Astro ne gérant que la présentation).

Diagnostic & Plan d’exécution — Découplage du Contenu /blog via Sanity

Date : 2026-10-18
Auteurs : Pair-programming Antigravity IDE & Anderson
Référence : Spécification utilisateur (plan/description.md), ADR-001
Dépôts cibles :

1. Diagnostic de l’existant sur /blog1/2

L’analyse du code source d’amn-blog et du dataset Sanity development (projet 4wa7mvsz) révèle une séparation incomplète entre contenu éditorial et présentation :

1. Diagnostic de l’existant sur /blog2/2

Éléments de la page /blog Composant Astro État actuel Piloté par Sanity ? Problème constaté
Liste des articles & pagination index.astro & BlogCard.astro Requête GROQ SSR dynamique : *[_type == "post"] paginée par 5 OUI (avec fallback Markdown local) Conforme à l’architecture.
Hero (Titre & Sous-titre) BlogHero.astro Valeurs codées en dur dans index.astro : title="Welcome, world", subtitle="Get all the latest news from the Amnworld." NON (Hardcodé dans Astro) Tout changement de slogan ou de titre nécessite un commit de code Astro.
Sidebar — Popular posts PopularPosts.astro Prend les 4 premiers posts récents, mais a une liste de 4 articles en dur (defaultPopularPosts) si vide. Pas de sélection éditoriale dans Sanity. PARTIELLEMENT L’éditeur ne peut pas choisir manuellement les articles mis en avant dans la sidebar.
Sidebar — Callout plateforme (“AMN platform”) MerchCallout.astro Titre, description, URL vers les docs et badges codés en dur dans le composant. NON (100% hardcodé) L’encart publicitaire/plateforme ne peut pas être modifié sans déployer le front.
Sidebar — Inscription RSS SubscribeRss.astro Titre “Subscribe” et sous-titre codés en dur. NON (Hardcodé) Textes figés dans le code Astro.
Métadonnées SEO du Blog index.astro -> MainLayout.astro title="Blog — Latest news & insights", description="..." passés en dur dans index.astro. NON (Hardcodé) Les métadonnées du blog ne sont pas configurables depuis Sanity.

Diagnostic de Sanity Studio (amn-studio)1/2

Dans amn-studio/schemaTypes/, les schémas existants sont :

  • post, author, category, blockContent
  • page (avec pageBuilder : hero, features, testimonials, cta, richText, imageGallery)
  • amn (document de test minimal avec message + status)
  • submission (formulaires)

Diagnostic de Sanity Studio (amn-studio)2/2

👉 Constat clé : Il n’existe aucun schéma blogSettings (ou réglages de page de blog) dans Sanity. C’est la raison pour laquelle les textes du hero, de la sidebar et du SEO avaient été initialement renseignés en dur dans Astro.

2. Architecture cible (Séparation stricte CMS / Présentation)1/2

Conformément à l’ADR-001 :

  • Sanity (amn-studio) = Contenu brut & Gouvernance éditoriale (titres, textes, slogans, liens, sélections d’articles populaires, encarts promo).
  • Astro (amn-blog) = Moteur de présentation pur (balisage HTML5 sémantique, design Tailwind CSS, responsive, accessibilité, rendu SSR).

2. Architecture cible (Séparation stricte CMS / Présentation)2/2

+-----------------------------------------------------------------------+
| SANITY STUDIO (amn-studio) |
| |
| Document Singleton "blogSettings" : |
| • heroTitle: "Welcome, world" |
| • heroSubtitle: "Get all the latest news from the Amnworld." |
| • popularPosts: [ Ref(post1), Ref(post2), Ref(post3) ] |
| • callout: { title, description, linkUrl, badgeText } |
| • subscribe: { title, subtitle, rssUrl } |
| • seo: { metaTitle, metaDescription, ogImage } |
+-----------------------------------▲-----------------------------------+
│ Requête GROQ SSR
│ (loadQuery)
+-----------------------------------▼-----------------------------------+
| ASTRO SSR (amn-blog) |
| |
| 1. index.astro fetch posts + blogSettings en une seule passe |
| 2. Injecte dynamiquement les données dans : |
| • <BlogHero title={settings.heroTitle} ... /> |
| • <BlogSidebar popularPosts={settings.popularPosts} ... /> |
| • <MainLayout title={settings.seo.metaTitle} ... /> |
| 3. Aucun texte de contenu en dur dans le code Astro |
+-----------------------------------------------------------------------+

3. Plan d’exécution par étapes

Étape 1 : Création du schéma blogSettings.ts dans amn-studio1/3

Ajouter le schéma singleton blogSettings avec les champs :

  • Hero :
    • heroTitle (string, titre d’accueil)
    • heroSubtitle (text, sous-titre)
  • Popular posts :
    • popularPosts (array de références vers post, avec prévisualisation)

Étape 1 : Création du schéma blogSettings.ts dans amn-studio2/3

  • Callout Encart Plateforme :
    • calloutTitle (string)
    • calloutDescription (text)
    • calloutLink (url / string)
    • calloutBadgeText (string, ex: “Audyssée architecture”)

Étape 1 : Création du schéma blogSettings.ts dans amn-studio3/3

  • Subscribe RSS :
    • subscribeTitle (string)
    • subscribeSubtitle (text)
  • SEO & Réseaux :
    • metaTitle (string)
    • metaDescription (text)
    • ogImage (image)

Enregistrer blogSettings dans amn-studio/schemaTypes/index.ts.

Étape 2 : Création & initialisation du document blogSettings dans le dataset Sanity

  • Via les outils MCP Sanity (create_documents) ou script, créer le document initial blogSettings avec les valeurs actuelles pour assurer une continuité parfaite sans rupture.

Étape 3 : Mise à jour de la requête GROQ dans amn-blog/src/pages/blog/index.astro

Adapter la requête pour récupérer posts, total ET settings en un seul appel :

{
"posts": *[_type == "post"] | order(publishedAt desc)[$start...$end] {
_id, title, slug, excerpt, publishedAt, mainImage { asset->{ url }, alt },
author->{ name, image { asset->{ url } } }, categories[]->{ _id, title }
},
"total": count(*[_type == "post"]),
"settings": *[_type == "blogSettings"][0] {
heroTitle,
heroSubtitle,
metaTitle,
metaDescription,
calloutTitle,
calloutDescription,
calloutLink,
calloutBadgeText,
subscribeTitle,
subscribeSubtitle,
"selectedPopularPosts": popularPosts[]->{
title,
"href": "/blog/" + slug.current + "/"
}
}
}

Étape 4 : Injection dynamique dans les composants Astro1/2

  1. BlogHero.astro : Reçoit title et subtitle depuis settings (avec fallback élégant si non défini).
  2. BlogSidebar.astro : Transmet les données dynamiques callout, subscribe et popularPosts à ses sous-composants.
  3. PopularPosts.astro : Utilise les articles sélectionnés dans Sanity (ou à défaut les articles les plus récents de Sanity).

Étape 4 : Injection dynamique dans les composants Astro2/2

  1. MerchCallout.astro : Affiche le titre, la description, le badge et le lien issus de settings.
  2. SubscribeRss.astro : Affiche les libellés issus de settings.
  3. MainLayout.astro : Reçoit metaTitle et metaDescription issus de settings.

Étape 5 : Validation & Traitement des retours utilisateurs (Feedback)1/3

Suite aux retours utilisateurs, les éléments complémentaires suivants ont été entièrement découplés et confiés à Sanity :

  1. Titre de la section “Popular posts” : Ajout du champ popularPostsTitle (string) dans le schéma blogSettings, récupéré dynamiquement et transmis à <PopularPosts title={popularPostsTitle} />.

  2. Visuel de l’encart callout (“Audyssée architecture”) & lien cliquable : Ajout du champ calloutImage (image avec hotspot) dans blogSettings. Le visuel est rendu sous forme de lien cliquable (<a href={href}>) avec l’image Sanity si fournie, ou avec le visuel vectoriel par défaut si aucune image n’est téléversée.

Étape 5 : Validation & Traitement des retours utilisateurs (Feedback)2/3

  1. Bouton & lien RSS Feed : Ajout des champs subscribeButtonLabel (“RSS Feed”) et subscribeRssLink (“/rss.xml”) dans blogSettings, transmis dynamiquement à <SubscribeRss />.

Étape 5 : Validation & Traitement des retours utilisateurs (Feedback)3/3

  1. Refonte visuelle du Merch Callout (conforme au style Astro) :

    • Élimination de la boîte/carte imbriquée interne autour du visuel.
    • Suppression du contour de carte (border border-purple-500/20, fond boîte) : la section s’intègre directement et harmonieusement dans la sidebar, délimitée uniquement par la bordure inférieure de section.
    • L’image occupe toute la largeur utile sous le titre et la description, avec coins arrondis (rounded-xl), intégrée dans un lien cliquable global (<a href={href}>).

4. Statut de réalisation1/2

Élément Propriété Sanity Statut
Titre du hero blogSettings.heroTitle ✅ Découplé & En ligne
Sous-titre du hero blogSettings.heroSubtitle ✅ Découplé & En ligne
Titre “Popular posts” blogSettings.popularPostsTitle ✅ Découplé & En ligne
Liste des articles populaires blogSettings.popularPosts[] ✅ Découplé & En ligne
Titre callout blogSettings.calloutTitle ✅ Découplé & En ligne
Description callout blogSettings.calloutDescription ✅ Découplé & En ligne

4. Statut de réalisation2/2

Élément Propriété Sanity Statut
Badge callout blogSettings.calloutBadgeText ✅ Découplé & En ligne
Image callout cliquable blogSettings.calloutImage + calloutLink ✅ Découplé & En ligne
Titre & Sous-titre subscribe blogSettings.subscribeTitle / subscribeSubtitle ✅ Découplé & En ligne
Libellé & URL bouton RSS blogSettings.subscribeButtonLabel / subscribeRssLink ✅ Découplé & En ligne
Métadonnées SEO blogSettings.metaTitle / metaDescription ✅ Découplé & En ligne
Switch to normal mode

Contents