Skip to content

Post

Post

Documentation technique

Type de ressource : Schéma Sanity (Document)
Fichier source : apps/studio/schemaTypes/post.ts
Statut : Actif
Slice : 2 (Blog)
Version : 1.0

1. Vue d’ensemble (DOC)

1.1. Description

Schéma principal pour les articles de blog du site. Contient les métadonnées de l’article (titre, slug, auteur, image, catégories, date de publication) et le corps du texte en Portable Text.

1.2. Objectif

  • Modéliser les articles de blog avec toutes les métadonnées nécessaires
  • Permettre l’association d’auteurs et de catégories aux articles
  • Supporter le contenu riche via Portable Text
  • Faciliter le rendu et l’indexation des articles

1.3. Cas d’usage

  • Création et édition d’articles de blog
  • Affichage des articles sur la page d’index du blog
  • Rendu des articles individuels avec leur contenu complet
  • Filtrage et tri des articles par auteur, catégories et date

1.4. Relations avec d’autres schémas

Relation Schéma Type Description
Dépend de author Référence Chaque article a un auteur obligatoire
Dépend de category Référence Un article peut avoir plusieurs catégories
Dépend de blockContent Composition Le champ body utilise le schéma blockContent
Utilisé par Aucun - Schéma racine, non référencé par d’autres

2. Structure des données (DOC)

2.1. Champs principaux

Nom du champ Type Obligatoire Description Validation
title string ✅ Titre de l’article de blog Aucune
slug slug ✅ Slug URL généré depuis le titre source: 'title', maxLength: 96
author reference ✅ Référence vers un auteur Référence vers author
mainImage image ❌ Image principale de l’article Hotspot activé
categories array ❌ Liste des catégories Références vers category
publishedAt datetime ✅ Date et heure de publication Aucune
body blockContent ✅ Corps du texte en Portable Text Utilise le schéma blockContent

2.2. Champs SEO

Aucun champ SEO spécifique n’est implémenté dans ce schéma.

2.3. Champs de contenu riche

Nom du champ Type Description
body array Contenu Portable Text (blocs + spans) via le schéma blockContent

3. Contrats d’Entrée/Sortie (SPEC)

3.1. Inputs (création/modification)

Champ Type Validation Description
title string Aucune Titre de l’article
slug slug source: 'title', maxLength: 96 Généré automatiquement depuis le titre
author reference Référence vers author Auteur obligatoire
publishedAt datetime Aucune Date de publication
body blockContent Aucune Contenu de l’article

3.2. Outputs (structure du document)1/2

Champ Type Description
_id string ID unique du document
_type string Type du document (post)
_createdAt string Date de création (généré par Sanity)
_updatedAt string Date de dernière modification (généré par Sanity)
title string Titre de l’article
slug { _type: 'slug'; current: string } Slug URL

3.2. Outputs (structure du document)2/2

Champ Type Description
author Author Référence vers le schéma author
mainImage ImageAsset Image principale (optionnel)
categories Category[] Liste des catégories (optionnel)
publishedAt string Date de publication
body PortableTextBlock[] Contenu Portable Text

3.3. États du document

Non implémenté - ce schéma n’a pas de champ status. Les documents sont toujours considérés comme publiés.

4. Implémentation (CODE)

4.1. Code du schéma1/2

4.1. Code du schéma2/2

apps/studio/schemaTypes/post.ts
import {defineField, defineType} from 'sanity'
export default defineType({
name: 'post',
title: 'Post',
type: 'document',
fields: [
defineField({
name: 'title',
title: 'Title',
type: 'string',
}),
defineField({
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
},
}),
defineField({
name: 'author',
title: 'Author',
type: 'reference',
to: {type: 'author'},
}),
defineField({
name: 'mainImage',
title: 'Main image',
type: 'image',
options: {
hotspot: true,
},
}),
defineField({
name: 'categories',
title: 'Categories',
type: 'array',
of: [{type: 'reference', to: {type: 'category'}}],
}),
defineField({
name: 'publishedAt',
title: 'Published at',
type: 'datetime',
}),
defineField({
name: 'body',
title: 'Body',
type: 'blockContent',
}),
],
preview: {
select: {
title: 'title',
author: 'author.name',
media: 'mainImage',
},
prepare(selection) {
const {author} = selection
return {...selection, subtitle: author && `by ${author}`}
},
},
})

4.2. Requêtes GROQ associées

Requête principale (listing)

*[_type == "post"] {
_id,
title,
slug,
publishedAt,
mainImage,
author->{name, slug},
categories[]->{title, slug}
} | order(publishedAt desc)

Requête détaillée (page unitaire)

*[_type == "post" && slug.current == $slug][0] {
_id,
title,
slug,
publishedAt,
mainImage,
author->{name, slug, image, bio},
categories[]->{title, slug, description},
body
}

4.3. Types TypeScript (génération automatique)

Non implémenté - sanity-typegen n’est pas configuré dans le projet actuel.

// Types à implémenter manuellement si nécessaire
export type Post = {
_id: string;
_type: 'post';
title: string;
slug: { _type: 'slug'; current: string };
author: Author;
mainImage?: ImageAsset;
categories?: Category[];
publishedAt: string;
body: PortableTextBlock[];
};

5. Tests attendus (TEST)

5.1. Tests unitaires

Scénario Description Résultat attendu
Validation du titre Créer un document sans titre Erreur de validation
Validation de l’auteur Créer un document sans auteur Erreur de validation
Génération du slug Créer un document avec titre Slug généré automatiquement depuis le titre
Limite du slug Créer un titre de plus de 96 caractères Slug tronqué à 96 caractères

5.2. Tests d’intégration

Scénario Dépendances Description Résultat attendu
Consommation Astro Route Astro + Sanity API Récupération des données via GROQ Données récupérées et typées correctement
Indexation Pagefind Build Astro + Pagefind Indexation du contenu généré Contenu des articles indexé et searchable
Preview Sanity Sanity Studio + Preview API Mode preview pour les drafts Preview fonctionne avec le secret

5.3. Tests E2E

Scénario Parcours utilisateur Description Résultat attendu
Création → Publication Sanity Studio → Build → Site Créer et publier un article Article visible sur le site avec toutes les métadonnées
Filtrage par catégorie Blog → Filtre catégorie Cliquer sur une catégorie Articles filtrés par catégorie

6. Intégration (INTÉG)

6.1. Intégration avec les composants

Composant Type Rôle Méthode d’intégration
Route Astro (blog/index.astro) L2 Listing des articles Requête GROQ via getSanityClient()
Route Astro (blog/[…slug].astro) L2 Page article individuelle Requête GROQ détaillée via getSanityClient()
Layout (BlogPost.astro) L2 Rendu de l’article Props passées depuis la route
Pagefind L2 Indexation Indexation du HTML généré par Astro

6.2. Points d’attention

  • Le schéma ne supporte pas les drafts (pas de champ status)
  • Les requêtes GROQ doivent utiliser les projections explicites
  • Le slug est utilisé pour générer les URLs des articles
  • L’auteur est obligatoire pour chaque article

6.3. Vérification de cohérence

  • Le schéma ne casse aucun schéma existant
  • Les requêtes GROQ retournent les données attendues
  • Les types TypeScript sont générés correctement (à implémenter)
  • Les tests E2E passent

7. Sécurité

7.1. Mécanismes de sécurité

  • ✅ Les références vers author et category sont validées par Sanity
  • ✅ Les images sont stockées dans Sanity Asset API avec accès contrôlé
  • ✅ Les permissions Sanity sont configurées par rôle

7.2. Validation des entrées

  • ✅ Les champs obligatoires (title, author, publishedAt, body) sont validés côté Sanity
  • ✅ Les slugs sont uniques et valides
  • ✅ Les références vers author et category pointent vers des documents existants

8. Performance et limites

8.1. Limites Sanity

Limite Valeur Stratégie d’optimisation
Taille du document 16 MB Éviter les champs body trop volumineux
Profondeur des références 10 niveaux Limiter les références imbriquées (author → categories)

8.2. Optimisations appliquées

  • ✅ Utilisation de projections GROQ pour réduire la taille des réponses
  • ✅ Mise en cache CDN pour les requêtes en production
  • ✅ Preview configuré pour désactiver le CDN en mode draft

9. Débogage et troubleshooting

9.1. Problèmes courants

Symptôme Cause probable Solution
Schéma non visible dans Studio Cache du navigateur Vider le cache et rafraîchir
Types TypeScript incorrects Schéma modifié sans régénération Exécuter sanity typegen generate (à implémenter)
Requête GROQ vide Filtre incorrect Vérifier la syntaxe GROQ
Auteur non affiché Référence cassée Vérifier que l’auteur existe et n’est pas supprimé

9.2. Commandes de debug

Terminal window
# Extraire le schéma depuis Sanity
npx sanity schema extract
# Générer les types TypeScript (à implémenter)
npx sanity typegen generate

10. Bonnes pratiques

10.1. Architecture

  • ✅ Toujours utiliser des types générés par sanity-typegen (à implémenter)
  • ✅ Centraliser les requêtes GROQ dans src/lib/queries.ts (à implémenter)
  • ✅ Documenter les champs et leurs validations

10.2. Code

  • ✅ Utiliser defineField pour chaque champ
  • ✅ Configurer le preview pour une meilleure UX dans Studio
  • ✅ Utiliser des validations appropriées

10.3. Maintenance

  • ✅ Mettre à jour ce fichier lors de toute modification du schéma
  • ✅ Régénérer les types après modification (à implémenter)
  • ✅ Tester les requêtes GROQ après modification

11. Évolutions et roadmap

11.1. Améliorations planifiées

  • Ajout de champs SEO (metaTitle, metaDescription, ogImage)
  • Implémentation de sanity-typegen pour la génération de types
  • Ajout d’un champ status pour supporter les drafts
  • Centralisation des requêtes GROQ dans un fichier dédié

11.2. Limitations connues

  • ❌ Pas de support pour les drafts (pas de champ status)
  • ❌ Pas de champs SEO spécifiques
  • ❌ Types TypeScript non générés automatiquement

12. Ressources liées

  • Documentation Sanity : Schema Types
  • DAT L1 : §4 - Modélisation et Schémas des Données
  • Schémas dépendants : author, category, blockContent
  • Pages Astro consommatrices : apps/web/src/pages/blog/index.astro, apps/web/src/pages/blog/[...slug].astro
  • Composants d’affichage : apps/web/src/layouts/BlogPost.astro

13. Historique des modifications

Date Version Description Auteur
2026-09-15 1.0 Création initiale Devin
Switch to normal mode

Contents