Diagnostic et plan - Découplage du contenu /blog via Sanity
Diagnostic & Plan d’exécution — Découplage du Contenu /blog via Sanity
Section titled “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 :
audyssee/amn-studio(Gestion des schémas & contenu CMS)audyssee/amn-blog(Présentation Astro SSR)
1. Diagnostic de l’existant sur /blog
Section titled “1. Diagnostic de l’existant sur /blog”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 :
É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)
Section titled “Diagnostic de Sanity Studio (amn-studio)”Dans amn-studio/schemaTypes/, les schémas existants sont :
post,author,category,blockContentpage(avecpageBuilder: hero, features, testimonials, cta, richText, imageGallery)amn(document de test minimal avec message + status)submission(formulaires)
👉 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)
Section titled “2. Architecture cible (Séparation stricte CMS / Présentation)”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).
+-----------------------------------------------------------------------+| 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
Section titled “3. Plan d’exécution par étapes”Étape 1 : Création du schéma blogSettings.ts dans amn-studio
Section titled “Étape 1 : Création du schéma blogSettings.ts dans amn-studio”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 verspost, avec prévisualisation)
- Callout Encart Plateforme :
calloutTitle(string)calloutDescription(text)calloutLink(url / string)calloutBadgeText(string, ex: “Audyssée architecture”)
- 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
Section titled “É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 initialblogSettingsavec 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
Section titled “É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 Astro
Section titled “Étape 4 : Injection dynamique dans les composants Astro”BlogHero.astro: Reçoittitleetsubtitledepuissettings(avec fallback élégant si non défini).BlogSidebar.astro: Transmet les données dynamiquescallout,subscribeetpopularPostsà ses sous-composants.PopularPosts.astro: Utilise les articles sélectionnés dans Sanity (ou à défaut les articles les plus récents de Sanity).MerchCallout.astro: Affiche le titre, la description, le badge et le lien issus desettings.SubscribeRss.astro: Affiche les libellés issus desettings.MainLayout.astro: ReçoitmetaTitleetmetaDescriptionissus desettings.
Étape 5 : Validation & Traitement des retours utilisateurs (Feedback)
Section titled “Étape 5 : Validation & Traitement des retours utilisateurs (Feedback)”Suite aux retours utilisateurs, les éléments complémentaires suivants ont été entièrement découplés et confiés à Sanity :
-
Titre de la section “Popular posts” : Ajout du champ
popularPostsTitle(string) dans le schémablogSettings, récupéré dynamiquement et transmis à<PopularPosts title={popularPostsTitle} />. -
Visuel de l’encart callout (“Audyssée architecture”) & lien cliquable : Ajout du champ
calloutImage(image avec hotspot) dansblogSettings. 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. -
Bouton & lien RSS Feed : Ajout des champs
subscribeButtonLabel(“RSS Feed”) etsubscribeRssLink(“/rss.xml”) dansblogSettings, transmis dynamiquement à<SubscribeRss />. -
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éalisation
Section titled “4. Statut de réalisation”| É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 |
| 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 |