Astro : contenu et collections
Les collections de contenu organisent des fichiers Markdown (ou JSON, YAML) avec un schéma vérifié à la compilation. Les exemples utilisent une collection blog et reprennent l’API d’Astro 7.
Définir une collection
Section intitulée « Définir une collection »src/content.config.ts :
import { defineCollection } from 'astro:content';import { glob } from 'astro/loaders';import { z } from 'astro/zod';
const blog = defineCollection({ loader: glob({ pattern: '**/*.md', base: './src/content/blog' }), schema: z.object({ titre: z.string(), description: z.string().max(160), date: z.coerce.date(), tags: z.array(z.string()).default([]), brouillon: z.boolean().default(false), }),});
export const collections = { blog };| Élément | Rôle |
|---|---|
loader: glob(...) |
Lit les fichiers correspondant au motif |
schema |
Valide le frontmatter (Zod) et type les données |
z.coerce.date() |
Convertit une chaîne de date en objet Date |
.default() |
Valeur par défaut |
Un fichier src/content/blog/premier-article.md :
---titre: 'Premier article'description: 'Un article de démonstration'date: 2026-01-15tags: ['astro', 'blog']---
Contenu **Markdown** de l'article.Si le frontmatter ne respecte pas le schéma, la compilation échoue avec un message précis (champ et règle).
Lire les entrées
Section intitulée « Lire les entrées »---import { getCollection, getEntry } from 'astro:content';
const articles = ( await getCollection('blog', ({ data }) => !data.brouillon)).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
const premier = await getEntry('blog', 'premier-article');---
<ul> {articles.map((a) => ( <li> <a href={`/blog/${a.id}/`}>{a.data.titre}</a> :{' '} {a.data.date.toLocaleDateString('fr-FR')} </li> ))}</ul>id est dérivé du nom de fichier (premier-article). Le filtre en second argument exclut par exemple les brouillons.
Générer une page par entrée
Section intitulée « Générer une page par entrée »src/pages/blog/[id].astro :
---import { getCollection, render } from 'astro:content';import Base from '../../layouts/Base.astro';
export async function getStaticPaths() { const articles = await getCollection('blog', ({ data }) => !data.brouillon); return articles.map((article) => ({ params: { id: article.id }, props: { article }, }));}
const { article } = Astro.props;const { Content, headings } = await render(article);---
<Base titre={article.data.titre} description={article.data.description}> <article> <h1>{article.data.titre}</h1> <Content /> </article></Base>render() renvoie le composant Content (le Markdown rendu) et la liste des titres (headings, utile pour une table des matières).
Autres formats de données
Section intitulée « Autres formats de données »const auteurs = defineCollection({ loader: glob({ pattern: '**/*.json', base: './src/content/auteurs' }), schema: z.object({ nom: z.string(), email: z.email() }),});Il existe aussi un loader file() pour un fichier unique contenant plusieurs entrées, et des loaders personnalisés (API distante, base de données).
Références entre collections
Section intitulée « Références entre collections »import { reference } from 'astro:content';
const blog = defineCollection({ loader: glob({ pattern: '**/*.md', base: './src/content/blog' }), schema: z.object({ titre: z.string(), auteur: reference('auteurs'), }),});---const auteur = await getEntry(article.data.auteur);---
<p>Par {auteur?.data.nom}</p>Markdown : options et limites
Section intitulée « Markdown : options et limites »- Syntaxe courante : titres, listes, tableaux, code, liens (GitHub Flavored Markdown).
- Astro 7 utilise par défaut un processeur Markdown natif (Sätteri) : les options
markdown.remarkPluginsetmarkdown.rehypePluginsne sont utilisables qu’en installant@astrojs/markdown-remarket en le configurant comme processeur. - Pour des composants dans le contenu, installer l’intégration MDX (
npx astro add mdx) et utiliser des fichiers.mdx. - Coloration du code : Shiki, intégrée (
markdown.shikiConfigpour choisir le thème).
Flux RSS et sitemap
Section intitulée « Flux RSS et sitemap »npx astro add sitemapnpm install @astrojs/rsssrc/pages/rss.xml.ts :
import rss from '@astrojs/rss';import { getCollection } from 'astro:content';
export async function GET(context) { const articles = await getCollection('blog', ({ data }) => !data.brouillon); return rss({ title: 'Mon blog', description: 'Les derniers articles', site: context.site, items: articles.map((a) => ({ title: a.data.titre, pubDate: a.data.date, description: a.data.description, link: `/blog/${a.id}/`, })), });}Dépannage
Section intitulée « Dépannage »| Symptôme | Piste |
|---|---|
Invalid frontmatter |
Un champ ne respecte pas le schéma : le message nomme le champ |
The collection "blog" does not exist |
Collection absente de collections dans content.config.ts |
| La collection est vide | Motif glob ou dossier base incorrects |
Cannot find module 'astro:content' |
Exécuter npx astro sync pour régénérer les types |
Le frontmatter casse sur un : |
Mettre la valeur entre guillemets |
| Date invalide | Utiliser z.coerce.date() et le format 2026-01-15 |
| Les images du contenu ne s’affichent pas | Chemin relatif au fichier Markdown, ou images dans public/ |
Ubuntu 24.04 et 26.04 : différences à connaître
Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »Aucune.