Ce guide couvre la création d’un blog avec EmDash, de la définition du type de contenu à l’affichage des articles avec catégories et tags.
Prérequis
- Un site EmDash configuré et fonctionnel (voir Démarrage)
- Connaissance de base des composants Astro
Définir la collection Posts
EmDash crée une collection “posts” par défaut lors de la configuration. Personnalisez-la depuis le tableau de bord admin ou l’API.
La collection posts par défaut inclut :
title- Titre de l’articleslug- Identifiant convivial pour les URLcontent- Corps en texte richeexcerpt- Description courtefeatured_image- Image d’en-tête (optionnel)status- brouillon, publié ou programmépublishedAt- Date de publication (champ système)
Créer votre premier article
-
Ouvrez le tableau de bord admin à
/_emdash/admin -
Cliquez sur Posts dans la barre latérale
-
Cliquez sur New Post
-
Entrez un titre et rédigez votre contenu avec l’éditeur de texte riche
-
Ajoutez des catégories et des tags dans le panneau latéral
-
Définissez le statut sur Publié
-
Cliquez sur Enregistrer
L’article est maintenant en ligne et apparaît immédiatement.
Afficher les articles sur votre site
Lister tous les articles
La page suivante affiche tous les articles publiés :
---
import { getEmDashCollection } from "emdash";
import Base from "../../layouts/Base.astro";
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Trier par date de publication, plus récents en premier
const sortedPosts = posts.sort(
(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0)
);
---
<Base title="Blog">
<h1>Blog</h1>
<ul>
{sortedPosts.map((post) => (
<li>
<a href={`/blog/${post.data.slug}`}>
<h2>{post.data.title}</h2>
<p>{post.data.excerpt}</p>
<time datetime={post.data.publishedAt?.toISOString()}>
{post.data.publishedAt?.toLocaleDateString()}
</time>
</a>
</li>
))}
</ul>
</Base>
Afficher un article individuel
La route dynamique suivante rend un article individuel :
---
import { getEmDashCollection, getEmDashEntry } from "emdash";
import { PortableText, Image } from "emdash/ui";
import Base from "../../layouts/Base.astro";
export async function getStaticPaths() {
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
return posts.map((post) => ({
params: { slug: post.data.slug },
}));
}
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
if (!post) {
return Astro.redirect("/404");
}
---
<Base title={post.data.title}>
<article>
{post.data.featured_image && (
<Image image={post.data.featured_image} alt="" />
)}
<h1>{post.data.title}</h1>
<time datetime={post.data.publishedAt?.toISOString()}>
{post.data.publishedAt?.toLocaleDateString()}
</time>
<PortableText value={post.data.content} />
</article>
</Base>
Ajouter des catégories et des tags
EmDash inclut des taxonomies de catégories et de tags intégrées. Voir Taxonomies pour les détails sur la création et la gestion des termes.
Filtrer les articles par catégorie
La route suivante liste les articles d’une seule catégorie :
---
import { getEmDashCollection, getTerm, getTaxonomyTerms } from "emdash";
import Base from "../../layouts/Base.astro";
export async function getStaticPaths() {
const categories = await getTaxonomyTerms("category");
// Aplatir les catégories hiérarchiques
const flatten = (terms) => terms.flatMap((t) => [t, ...flatten(t.children)]);
return flatten(categories).map((cat) => ({
params: { slug: cat.slug },
props: { category: cat },
}));
}
const { category } = Astro.props;
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
where: { category: category.slug },
});
---
<Base title={category.label}>
<h1>{category.label}</h1>
{category.description && <p>{category.description}</p>}
<ul>
{posts.map((post) => (
<li>
<a href={`/blog/${post.data.slug}`}>{post.data.title}</a>
</li>
))}
</ul>
</Base>
Afficher les catégories d’un article
Le composant suivant affiche les catégories et tags assignés à un article :
---
import { getEntryTerms } from "emdash";
interface Props {
postId: string;
}
const { postId } = Astro.props;
const categories = await getEntryTerms("posts", postId, "category");
const tags = await getEntryTerms("posts", postId, "tag");
---
<div class="post-meta">
{categories.length > 0 && (
<div class="categories">
<span>Catégories :</span>
{categories.map((cat) => (
<a href={`/category/${cat.slug}`}>{cat.label}</a>
))}
</div>
)}
{tags.length > 0 && (
<div class="tags">
<span>Tags :</span>
{tags.map((tag) => (
<a href={`/tag/${tag.slug}`}>{tag.label}</a>
))}
</div>
)}
</div>
Ajouter la pagination
Pour les blogs avec beaucoup d’articles, la route suivante pagine la liste des articles :
---
import { getEmDashCollection } from "emdash";
import Base from "../../../layouts/Base.astro";
const POSTS_PER_PAGE = 10;
export async function getStaticPaths() {
const { entries: allPosts } = await getEmDashCollection("posts", {
status: "published",
});
const totalPages = Math.ceil(allPosts.length / POSTS_PER_PAGE);
return Array.from({ length: totalPages }, (_, i) => ({
params: { page: String(i + 1) },
props: { currentPage: i + 1, totalPages },
}));
}
const { currentPage, totalPages } = Astro.props;
const { entries: allPosts } = await getEmDashCollection("posts", {
status: "published",
});
const sortedPosts = allPosts.sort(
(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0)
);
const start = (currentPage - 1) * POSTS_PER_PAGE;
const posts = sortedPosts.slice(start, start + POSTS_PER_PAGE);
---
<Base title={`Blog - Page ${currentPage}`}>
<h1>Blog</h1>
<ul>
{posts.map((post) => (
<li>
<a href={`/blog/${post.data.slug}`}>{post.data.title}</a>
</li>
))}
</ul>
<nav>
{currentPage > 1 && (
<a href={`/blog/page/${currentPage - 1}`}>Précédent</a>
)}
<span>Page {currentPage} sur {totalPages}</span>
{currentPage < totalPages && (
<a href={`/blog/page/${currentPage + 1}`}>Suivant</a>
)}
</nav>
</Base>
Ajouter un flux RSS
Le endpoint suivant génère un flux RSS pour le blog :
import rss from "@astrojs/rss";
import { getEmDashCollection } from "emdash";
export async function GET(context) {
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
return rss({
title: "Mon Blog",
description: "Un blog construit avec EmDash",
site: context.site,
items: posts.map((post) => ({
title: post.data.title,
pubDate: post.data.publishedAt,
description: post.data.excerpt,
link: `/blog/${post.data.slug}`,
})),
});
}
Le flux dépend du package @astrojs/rss. La commande suivante l’installe :
npm install @astrojs/rss
Étapes suivantes
- Travailler avec le contenu - Apprendre les opérations CRUD dans l’admin
- Médiathèque - Ajouter des images à vos articles
- Taxonomies - Créer des systèmes de classification personnalisés