Il template blog di EmDash fornisce un sito Astro funzionante con articoli, pagine, autori, categorie, tag, ricerca, commenti, widget e un feed RSS. Questo tutorial crea la versione Cloudflare, pubblica un articolo e segue quell’articolo attraverso il codice del template.
Prerequisiti
Prima di iniziare, installa Node.js 22.12 o successivo e pnpm.
Ti serve un account Cloudflare solo quando distribuisci il sito. Durante lo sviluppo locale, il template esegue sul tuo computer versioni locali del database e dell’archiviazione dei file.
Creare la struttura del blog
Il comando seguente crea my-blog a partire dal template blog di Cloudflare e installa le sue dipendenze con pnpm:
npm create emdash@latest my-blog -- --template cloudflare:blog --pm pnpm --yes
Lo scaffolder crea anche un file .env locale con una EMDASH_ENCRYPTION_KEY. Il .gitignore generato esclude .env dal controllo di versione. Se il comando segnala che l’installazione delle dipendenze è fallita, entra nella directory del progetto ed esegui pnpm install prima di continuare.
Avvia il server di sviluppo locale:
cd my-blog
pnpm dev
Apri l’URL locale stampato nel terminale, poi apri /_emdash/admin. Completa la schermata di configurazione se è la prima esecuzione. I dati seed del template creano il modello di contenuto e i contenuti di esempio durante la configurazione.
Comprendere il modello di contenuto
Il template definisce due collezioni in seed/seed.json:
postsabilita bozze, revisioni, ricerca e SEO tramitesupports, e abilita i commenti separatamente concommentsEnabled: true;pagessupporta bozze, revisioni e ricerca.
Ogni articolo ha questi campi personalizzati:
| Campo | Scopo |
|---|---|
title | Titolo obbligatorio dell’articolo |
featured_image | Immagine facoltativa mostrata con l’articolo |
content | Corpo in Portable Text |
excerpt | Breve testo usato negli elenchi di articoli e come valore di ripiego per i metadati |
EmDash aggiunge campi di sistema come l’ID di contenuto stabile, lo slug, lo stato, gli orari di creazione e aggiornamento e l’orario di pubblicazione. Il template definisce anche le tassonomie category e tag per gli articoli, oltre a byline che possono attribuire il lavoro a uno o più autori.
Il server di sviluppo genera emdash-env.d.ts da questo schema. Di conseguenza, getEmDashCollection("posts") restituisce voci la cui proprietà data è tipizzata come Post.
Pubblicare il primo articolo
-
Nella barra laterale dell’amministrazione, seleziona Posts, poi Add New.
-
Inserisci un titolo. EmDash suggerisce uno slug a partire dal titolo; modificalo se l’URL pubblico richiede un valore diverso.
-
Aggiungi un estratto e scrivi il corpo nell’editor Content.
-
Seleziona un’immagine in evidenza dalla libreria media oppure caricane una. Aggiungi un testo alternativo che descriva lo scopo dell’immagine nell’articolo.
-
Assegna una byline, una categoria e gli eventuali tag pertinenti nel pannello delle impostazioni.
-
Seleziona Save. La voce diventa una bozza e l’editor apre il suo URL permanente.
-
Seleziona Preview e controlla la pagina dell’articolo. Torna all’editor e seleziona Publish quando la bozza è pronta.
Apri /posts/your-post-slug sul sito locale. L’articolo compare anche nella home page e nell’archivio degli articoli. Se non compare, verifica che l’editor mostri Published invece di Draft o Scheduled.
Dopo la pubblicazione, le modifiche vengono salvate automaticamente in una nuova bozza mentre l’articolo attuale resta online. Seleziona Publish changes quando la bozza rivista deve sostituirlo. La guida alla creazione dei contenuti spiega anteprime, pianificazione, revisioni e blocchi di modifica.
Seguire la query della collezione
La home page e l’archivio degli articoli chiamano getEmDashCollection() durante il rendering sul server. Il template ordina gli articoli nel database in base al campo memorizzato 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 query della collezione restituisce per impostazione predefinita le voci pubblicate. Per l’ordinamento usa published_at, il nome del campo nel database. La proprietà publishedAt restituita è un Date JavaScript per il rendering.
L’helper delle tassonomie riceve post.data.id perché le assegnazioni di tassonomia appartengono all’ID di contenuto stabile. I link usano invece post.id, perché è lo slug rivolto all’URL prodotto dal content loader:
<a href={`/posts/${post.id}`}>
<h2>{post.data.title}</h2>
{post.data.excerpt && <p>{post.data.excerpt}</p>}
</a>
Il template attuale raggruppa le ricerche dei tag con getTermsForEntries() invece di eseguire una query per ogni articolo. Le byline sono già incluse in post.data.bylines dalla query della collezione.
Seguire la query dell’articolo
La route dinamica dell’articolo legge lo slug dall’URL e chiama getEmDashEntry(). L’estratto seguente mostra il percorso essenziale di query e rendering, mentre il template completo gestisce anche SEO, byline, commenti, articoli correlati e widget:
---
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 legge il valore del media selezionato dall’editor e genera un output responsive. PortableText trasforma i dati dei blocchi memorizzati in intestazioni, paragrafi, link, immagini, blocchi di codice e negli altri tipi di blocco supportati.
Entrambi i template blog impostano output: "server" in astro.config.mjs. Queste query vengono eseguite quando una richiesta viene renderizzata, quindi i contenuti pubblicati non dipendono da un elenco statico di route creato durante la build.
Usare categorie e tag
Il template include route di archivio per ogni categoria e ogni tag. La route di una categoria risolve prima lo slug del termine, poi filtra gli articoli in base a quella tassonomia:
---
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 usa lo stesso schema con getTerm("tag", slug) e where: { tag: term.slug }. Gli editor gestiscono termini e assegnazioni nell’amministrazione; la guida alle tassonomie tratta le categorie gerarchiche, i tag piatti e le tassonomie personalizzate.
getEmDashEntry() include i termini assegnati all’articolo, quindi la route di dettaglio può renderizzarli senza un’altra query:
---
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>
))}
Aggiungere la paginazione all’archivio
L’archivio degli articoli del template renderizza ogni articolo pubblicato. Quando l’archivio cresce, aggiungi un limit e usa la paginazione a offset per route numerate come /posts/page/2, oppure la paginazione a cursore per un link Older posts. Mantieni invariato orderBy: { published_at: "desc" } tra le pagine, in modo che l’ordine delle voci non cambi in modo imprevisto.
Gli esempi di paginazione mostrano entrambi gli approcci e spiegano quando scegliere l’uno o l’altro.
Controllare il feed RSS
Il template serve già /rss.xml. Il suo endpoint legge i 20 articoli più recenti con getEmDashCollection(), formatta ogni data di pubblicazione ed esegue l’escape di titolo ed estratto prima di inserirli nell’XML. Legge inoltre il titolo e il sottotitolo del sito dalle impostazioni di EmDash.
Dopo aver pubblicato l’articolo di prova, apri /rss.xml e cerca il suo titolo. Se il sito userà un URL assoluto di produzione nei feed, imposta l’opzione site di Astro prima della distribuzione; durante lo sviluppo locale, l’endpoint ripiega sull’origine della richiesta corrente.
A questo punto il blog dispone di un flusso di creazione, pagine degli articoli a runtime, archivi delle tassonomie, rendering dei media e un feed. Continua con Interrogare i contenuti per filtri e paginazione, oppure con Libreria media per la modifica degli asset e il tracciamento del loro utilizzo. Per redigere o modificare articoli con un assistente IA, segui Strumenti di IA.