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
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écessaireexport 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
# Extraire le schéma depuis Sanitynpx sanity schema extract
# Générer les types TypeScript (à implémenter)npx sanity typegen generate10. 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
defineFieldpour 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 |