Créer un Blog

Sur cette page

Le modèle de blog EmDash fournit un site Astro fonctionnel avec des articles, des pages, des auteurs, des catégories, des tags, la recherche, des commentaires, des widgets et un flux RSS. Ce tutoriel crée la version Cloudflare, publie un article et suit cet article à travers le code du modèle.

Prérequis

Installez Node.js 22.12 ou une version ultérieure ainsi que pnpm avant de commencer.

Vous n’avez besoin d’un compte Cloudflare que pour déployer le site. Pendant le développement local, le modèle exécute sur votre ordinateur des versions locales de la base de données et du stockage de fichiers.

Créer la structure du blog

La commande suivante crée my-blog à partir du modèle de blog Cloudflare et installe ses dépendances avec pnpm :

npm create emdash@latest my-blog -- --template cloudflare:blog --pm pnpm --yes

L’outil de génération crée également un fichier .env local contenant une EMDASH_ENCRYPTION_KEY. Le .gitignore généré exclut .env du contrôle de version. Si la commande signale que l’installation des dépendances a échoué, placez-vous dans le répertoire du projet et exécutez pnpm install avant de continuer.

Démarrez le serveur de développement local :

cd my-blog
pnpm dev

Ouvrez l’URL locale affichée dans le terminal, puis ouvrez /_emdash/admin. Terminez l’écran de configuration s’il s’agit du premier lancement. Les données seed du modèle créent le modèle de contenu et un contenu d’exemple pendant la configuration.

Comprendre le modèle de contenu

Le modèle définit deux collections dans seed/seed.json :

  • posts active les brouillons, les révisions, la recherche et le SEO via supports, et active les commentaires séparément avec commentsEnabled: true ;
  • pages prend en charge les brouillons, les révisions et la recherche.

Chaque article possède ces champs personnalisés :

ChampRôle
titleTitre obligatoire de l’article
featured_imageImage facultative affichée avec l’article
contentCorps en Portable Text
excerptTexte court utilisé dans les listes d’articles et comme valeur de repli pour les métadonnées

EmDash ajoute des champs système tels que l’ID de contenu stable, le slug, le statut, les dates de création et de mise à jour, ainsi que la date de publication. Le modèle définit aussi les taxonomies category et tag pour les articles, ainsi que des bylines pouvant créditer un ou plusieurs auteurs.

Le serveur de développement génère emdash-env.d.ts à partir de ce schéma. Par conséquent, getEmDashCollection("posts") renvoie des entrées dont la propriété data est typée Post.

Publier le premier article

  1. Dans la barre latérale de l’administration, sélectionnez Posts, puis Add New.

  2. Saisissez un titre. EmDash suggère un slug à partir du titre ; modifiez-le si l’URL publique doit avoir une autre valeur.

  3. Ajoutez un extrait et rédigez le corps dans l’éditeur Content.

  4. Sélectionnez une image mise en avant dans la médiathèque ou importez-en une. Ajoutez un texte alternatif décrivant le rôle de l’image dans l’article.

  5. Attribuez un byline, une catégorie et les tags pertinents dans le panneau des paramètres.

  6. Sélectionnez Save. L’entrée devient un brouillon et l’éditeur ouvre son URL permanente.

  7. Sélectionnez Preview et vérifiez la page de l’article. Revenez à l’éditeur et sélectionnez Publish lorsque le brouillon est prêt.

Ouvrez /posts/your-post-slug sur le site local. L’article apparaît aussi sur la page d’accueil et dans l’archive des articles. S’il n’apparaît pas, vérifiez que l’éditeur affiche Published plutôt que Draft ou Scheduled.

Après la publication, les modifications sont enregistrées automatiquement dans un nouveau brouillon tandis que l’article actuel reste en ligne. Sélectionnez Publish changes lorsque le brouillon révisé doit le remplacer. Le guide de création de contenu explique les aperçus, la planification, les révisions et les verrous d’édition.

Suivre la requête de collection

La page d’accueil et l’archive des articles appellent getEmDashCollection() pendant le rendu côté serveur. Le modèle trie les articles dans la base de données selon le champ stocké published_at :

---
import { getEmDashCollection, getTermsForEntries } from "emdash";

const { entries: posts, cacheHint } = await getEmDashCollection("posts", {
  orderBy: { published_at: "desc" },
});

if (Astro.cache?.enabled) Astro.cache.set(cacheHint);

const tagsByEntry = await getTermsForEntries(
  "posts",
  posts.map((post) => post.data.id),
  "tag",
);
---

La requête de collection renvoie par défaut les entrées publiées. Elle utilise published_at, le nom du champ en base de données, pour le tri. La propriété publishedAt renvoyée est un Date JavaScript destiné au rendu.

L’assistant de taxonomie reçoit post.data.id parce que les affectations de taxonomie appartiennent à l’ID de contenu stable. Les liens utilisent en revanche post.id, car c’est le slug destiné à l’URL que produit le chargeur de contenu :

<a href={`/posts/${post.id}`}>
  <h2>{post.data.title}</h2>
  {post.data.excerpt && <p>{post.data.excerpt}</p>}
</a>

Le modèle actuel regroupe les recherches de tags avec getTermsForEntries() au lieu d’effectuer une requête par article. Les bylines sont déjà incluses dans post.data.bylines par la requête de collection.

Suivre la requête d’article

La route dynamique de l’article lit le slug dans l’URL et appelle getEmDashEntry(). L’extrait suivant montre le chemin essentiel de requête et de rendu, alors que le modèle complet gère aussi le SEO, les bylines, les commentaires, les articles associés et les widgets :

---
import { decodeSlug, getEmDashEntry } from "emdash";
import { Image, PortableText } from "emdash/ui";

const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.rewrite("/404");

const { entry: post, error, cacheHint } = await getEmDashEntry("posts", slug);

if (error) return new Response("Unable to load post", { status: 500 });
if (!post) return Astro.rewrite("/404");
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---

<article>
  {post.data.featured_image && <Image image={post.data.featured_image} priority />}
  <h1>{post.data.title}</h1>
  <PortableText value={post.data.content} />
</article>

Image lit la valeur de média sélectionnée par l’éditeur et génère un rendu adaptatif. PortableText transforme les données de blocs stockées en titres, paragraphes, liens, images, blocs de code et autres types de blocs pris en charge.

Les deux modèles de blog définissent output: "server" dans astro.config.mjs. Ces requêtes s’exécutent lorsqu’une requête est rendue ; le contenu publié ne dépend donc pas d’une liste de routes statiques créée pendant le build.

Utiliser les catégories et tags

Le modèle inclut des routes d’archive pour chaque catégorie et chaque tag. Une route de catégorie résout d’abord le slug du terme, puis filtre les articles selon cette taxonomie :

---
import { decodeSlug, getEmDashCollection, getTerm } from "emdash";

const slug = decodeSlug(Astro.params.slug);
const category = slug
  ? await getTerm("category", slug, { includeCounts: false })
  : null;

if (!category) return Astro.rewrite("/404");

const { entries: posts, error } = await getEmDashCollection("posts", {
  where: { category: category.slug },
  orderBy: { published_at: "desc" },
});

if (error) return new Response("Unable to load posts", { status: 500 });
---

La route tag suit le même schéma avec getTerm("tag", slug) et where: { tag: term.slug }. Les éditeurs gèrent les termes et les affectations dans l’administration ; le guide des taxonomies couvre les catégories hiérarchiques, les tags plats et les taxonomies personnalisées.

getEmDashEntry() inclut les termes affectés à l’article, ce qui permet à la route de détail de les afficher sans requête supplémentaire :

---
const categories = post.data.terms?.category ?? [];
const tags = post.data.terms?.tag ?? [];
---

{categories.map((category) => (
  <a href={`/category/${category.slug}`}>{category.label}</a>
))}
{tags.map((tag) => (
  <a href={`/tag/${tag.slug}`}>{tag.label}</a>
))}

Ajouter la pagination de l’archive

L’archive des articles du modèle affiche chaque article publié. Lorsque l’archive grossit, ajoutez une limit et utilisez la pagination par décalage pour des routes numérotées comme /posts/page/2, ou la pagination par curseur pour un lien Older posts. Conservez orderBy: { published_at: "desc" } inchangé d’une page à l’autre afin que l’ordre des entrées ne change pas de façon inattendue.

Les exemples de pagination présentent les deux approches et expliquent quand choisir l’une ou l’autre.

Vérifier le flux RSS

Le modèle sert déjà /rss.xml. Son point de terminaison lit les 20 articles les plus récents avec getEmDashCollection(), formate chaque date de publication et échappe le titre et l’extrait avant de les insérer dans le XML. Il lit aussi le titre et le slogan du site depuis les paramètres EmDash.

Après avoir publié l’article de test, ouvrez /rss.xml et recherchez son titre. Si le site doit utiliser une URL absolue de production dans les flux, définissez l’option site d’Astro avant le déploiement ; pendant le développement local, le point de terminaison se rabat sur l’origine de la requête courante.

À ce stade, le blog dispose d’un flux de travail de rédaction, de pages d’articles à l’exécution, d’archives de taxonomies, d’un rendu des médias et d’un flux. Poursuivez avec Interroger le contenu pour les filtres et la pagination, ou avec Médiathèque pour la modification des ressources et le suivi de leur utilisation. Pour rédiger ou modifier des articles avec un assistant IA, suivez Outils d’IA.