EmDash 部落格範本提供一個功能完整的 Astro 網站,包含文章、頁面、作者、分類、標籤、搜尋、留言、小工具和 RSS 訂閱。本教學將建立 Cloudflare 版本,發布一篇文章,並透過範本程式碼追蹤該文章。
先決條件
開始前請安裝 Node.js 22.12 或更高版本以及 pnpm。
只有在部署網站時才需要 Cloudflare 帳戶。在本地開發期間,範本會在你的電腦上執行資料庫和檔案儲存的本地版本。
建立部落格
以下命令從 Cloudflare 部落格範本建立 my-blog 並使用 pnpm 安裝相依套件:
npm create emdash@latest my-blog -- --template cloudflare:blog --pm pnpm --yes
腳手架工具還會建立包含 EMDASH_ENCRYPTION_KEY 的本地 .env 檔案。產生的 .gitignore 會將 .env 從版本控制中排除。如果命令報告相依套件安裝失敗,請進入專案目錄並在繼續前執行 pnpm install。
啟動本地開發伺服器:
cd my-blog
pnpm dev
開啟終端機中顯示的本地 URL,然後開啟 /_emdash/admin。如果是首次執行,請完成設定畫面。範本的種子資料會在設定期間建立內容模型和範例內容。
瞭解內容模型
範本在 seed/seed.json 中定義了兩個集合:
posts透過supports啟用草稿、修訂、搜尋和 SEO,並透過commentsEnabled: true單獨啟用留言;pages支援草稿、修訂和搜尋。
每篇文章有以下自訂欄位:
| 欄位 | 用途 |
|---|---|
title | 必填的文章標題 |
featured_image | 與文章一起顯示的選填圖片 |
content | Portable Text 內文 |
excerpt | 用於文章列表和中繼資料備援的短文 |
EmDash 會新增系統欄位,如穩定的內容 ID、slug、狀態、建立和更新時間以及發布時間。範本還為文章定義了 category 和 tag 分類法,以及可以標註一位或多位作者的署名列。
開發伺服器會從此結構描述產生 emdash-env.d.ts。因此,getEmDashCollection("posts") 回傳的項目其 data 屬性型別為 Post。
發布第一篇文章
-
在管理側邊欄中,選擇 Posts,然後選擇 Add New。
-
輸入標題。EmDash 會從標題建議一個 slug;如果公開 URL 需要不同的值,請編輯它。
-
新增摘要並在 Content 編輯器中撰寫內文。
-
從媒體庫選擇或上傳特色圖片。新增描述圖片在文章中用途的替代文字。
-
在設定面板中指派署名列、分類和相關標籤。
-
選擇 Save。項目將變為草稿,編輯器會開啟其永久項目 URL。
-
選擇 Preview 並檢查文章頁面。返回編輯器,當草稿準備就緒時選擇 Publish。
在本地網站開啟 /posts/your-post-slug。文章也會出現在首頁和文章封存中。如果沒有出現,請確認編輯器顯示的是 Published,而不是 Draft 或 Scheduled。
發布後,編輯內容會自動儲存到新草稿,而目前文章保持上線。當修訂後的草稿應該取代時,選擇 Publish changes。內容撰寫指南說明了預覽、排程、修訂和編輯鎖定。
追蹤集合查詢
首頁和文章封存在伺服器渲染期間呼叫 getEmDashCollection()。範本按儲存的 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",
);
---
集合查詢預設回傳已發布的項目。它使用資料庫欄位名稱 published_at 進行排序。回傳的 publishedAt 屬性是用於渲染的 JavaScript Date。
分類法輔助程式接收 post.data.id,因為分類法指派屬於穩定的內容 ID。連結則使用 post.id,因為那是內容載入器產生的面向 URL 的 slug:
<a href={`/posts/${post.id}`}>
<h2>{post.data.title}</h2>
{post.data.excerpt && <p>{post.data.excerpt}</p>}
</a>
目前範本使用 getTermsForEntries() 批次查詢標籤,而不是為每篇文章單獨查詢一次。署名列已經透過集合查詢包含在 post.data.bylines 中。
追蹤文章查詢
動態文章路由從 URL 讀取 slug 並呼叫 getEmDashEntry()。以下摘錄展示了基本的查詢和渲染路徑,而完整範本還處理 SEO、署名列、留言、相關文章和小工具:
---
import { decodeSlug, getEmDashEntry } from "emdash";
import { Image, PortableText } from "emdash/ui";
const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.redirect("/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.redirect("/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 讀取編輯器選擇的媒體值並產生響應式輸出。PortableText 將儲存的區塊資料轉換為標題、段落、連結、圖片、程式碼區塊和其他支援的區塊類型。
兩個部落格範本都在 astro.config.mjs 中設定了 output: "server"。這些查詢在請求被渲染時執行,因此發布的內容不依賴於建置期間建立的靜態路由列表。
使用分類和標籤
範本包含每個分類和標籤的封存路由。分類路由首先解析術語 slug,然後按該分類法過濾文章:
---
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.redirect("/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 });
---
tag 路由使用相同的模式,即 getTerm("tag", slug) 和 where: { tag: term.slug }。編輯者在管理後台管理術語和指派;分類法指南涵蓋了層級分類、扁平標籤和自訂分類法。
getEmDashEntry() 包含文章的已指派術語,因此詳情路由無需額外查詢即可渲染它們:
---
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>
))}
新增封存分頁
範本的文章封存渲染所有已發布的文章。當封存增長時,新增 limit 並對 /posts/page/2 等編號路由使用位移分頁,或對更早的文章連結使用游標分頁。不要在頁面之間更改 orderBy: { published_at: "desc" },以免項目順序意外改變。
分頁範例展示了兩種方法並說明了何時選擇每種方法。
檢查 RSS 訂閱
範本已經提供 /rss.xml。該端點使用 getEmDashCollection() 讀取最新的 20 篇文章,格式化每個發布日期,並在插入 XML 之前跳脫標題和摘要。它還從 EmDash 設定中讀取網站標題和標語。
發布測試文章後,開啟 /rss.xml 並搜尋其標題。如果網站將在訂閱中使用絕對正式 URL,請在部署前設定 Astro 的 site 選項;端點在本地開發期間會回退到目前請求來源。
此時部落格已經擁有撰寫工作流程、執行階段文章頁面、分類法封存、媒體渲染和訂閱。繼續閱讀查詢內容瞭解篩選和分頁,或媒體庫瞭解資產編輯和使用追蹤。要使用 AI 助手起草或編輯文章,請參閱 AI 工具。