La moitié visible d’un thème, c’est le design. La moitié qui décide si vous aimez encore ce thème dans dix-huit mois, c’est la couche de contenu — et dans Astro, cela veut dire les collections de contenu.
Un schéma est un contrat avec votre moi futur
Le schéma d’une collection déclare ce qu’un contenu a le droit de contenir. Un article de blog a un titre, une description, une date, exactement une catégorie, exactement un auteur, une image facultative et un booléen qui dit s’il est mis en avant. Tout le reste fait échouer la compilation.
Cela paraît contraignant, jusqu’à la première fois où quelqu’un ajoute un article dont la date est écrite comme une chaîne de caractères plutôt que comme une date, ou fait une faute de frappe dans le slug d’une catégorie. Sans schéma, ces erreurs partent en production sans un bruit et ressurgissent sous la forme d’une page blanche. Avec un schéma, elles ressurgissent sous la forme d’une compilation en échec, avec le nom du fichier dedans.
const blog = defineCollection({
type: 'content',
schema: ({ image }) => z.object({
title: z.string(),
description: z.string(),
date: z.date(),
category: reference('categories'),
author: reference('authors'),
image: image().optional(),
featured: z.boolean().default(false),
}),
});
Les références sont ce qui fait du site un site
reference('authors') fait plus de travail qu’il n’y paraît. Cela signifie que l’auteur d’un article n’est pas une chaîne qui se trouve correspondre à un nom quelque part ailleurs : c’est un pointeur vers une entrée d’une autre collection, validé à la compilation. Renommez un fichier d’auteur et chaque article qui pointait vers lui échoue bruyamment, au lieu d’afficher une signature vide.
Concrètement, c’est ce qui permet à un thème de générer les pages d’auteur et les pages de catégorie à partir des mêmes données que celles qui rendent l’article. Une source, trois templates de route, aucune liste dupliquée à garder synchronisée. C’est aussi la structure que les moteurs de recherche peuvent réellement suivre : chaque article renvoie vers son auteur et sa catégorie, et ces deux pages renvoient à leur tour vers l’ensemble complet.
La fonction image() mérite sa place
Déclarer image: image().optional() dans le schéma signifie que le chemin indiqué dans le frontmatter est résolu et validé comme n’importe quel autre champ, et que le résultat est un objet image typé plutôt qu’une chaîne. Passez-le au composant <Image /> d’Astro et vous obtenez du WebP généré, les largeurs que vous avez demandées, et les dimensions intrinsèques écrites dans le balisage, pour que la mise en page ne bouge pas pendant le chargement.
Rien de tout cela n’exige que quelqu’un dans l’équipe pense à convertir un fichier avant de l’ajouter au dépôt — et c’est le seul flux de travail d’images qui survive au contact d’un vrai projet.
Là où la structure se voit
Vous ne voyez rien de tout cela sur la page d’accueil. Vous le voyez au onzième article, quand l’ajouter prend quatre minutes et ne touche qu’un seul fichier.