用 frontmatter 的 slug 自訂文章網址
前言
在使用 Astro 建立部落格時,你一定會遇到一個需求:
👉 讓文章網址不是用檔名,而是用你自訂的 slug
例如:
/blog/astro-intro
而不是:
/blog/post-1
這篇文章會教你如何在 Astro 中,透過 frontmatter 的 slug 來控制文章網址。
🎯 最終效果
你在 Markdown 寫:
---
title: Astro 入門教學
slug: astro-intro
---
👉 網址會變成:
/blog/astro-intro
🧠 核心概念
Astro 預設是:
👉 用「檔名」當網址(slug)
但你可以改成:
👉 用「frontmatter 的 slug」當網址
🚀 實作步驟
🧩 Step 1:在 frontmatter 加入 slug
---
title: Astro 入門教學
slug: astro-intro
date: 2026-03-28T14:00:00
---
📁 Step 2:建立動態路由
建立檔案:
src/pages/blog/[slug].astro
👉 這代表網址會是:
/blog/xxx
⚙️ Step 3:用 slug 產生頁面
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: {
slug: post.data.slug, // 👈 使用 frontmatter 的 slug
},
props: {
post,
},
}));
}
const { post } = Astro.props;
---
<h1>{post.data.title}</h1>
<article>
<post.Content />
</article>
🔥 這段程式在做什麼?
slug: post.data.slug
👉 意思是:
「用 frontmatter 裡的 slug 當網址參數」
⚠️ 重要注意事項
❗slug 必須唯一
slug: astro-intro
👉 每篇文章都不能重複,否則會:
- 路由衝突
- build 失敗
❗建議加 schema 驗證(強烈推薦)
slug: z.string()
👉 避免忘記填 slug
❗沒寫 slug 會壞掉
如果你直接用:
post.data.slug
👉 沒寫 slug 的文章會:
- 無法產生頁面
- 或網址變成 undefined
🧠 改進做法(更穩定)
建議加 fallback:
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: {
slug: post.data.slug || post.slug, // 👈 fallback
},
props: { post },
}));
}
---
🔥 最佳實務(推薦)
---
title: Astro 入門教學
slug: astro-intro
date: 2026-03-28T14:00:00
published: true
---
搭配:
slug: z.string()
🧠 常見問題:
Q:可以不用 slug 嗎?
可以 👉 Astro 會用檔名當網址
Q: slug 跟檔名哪個比較好?
| 方法 | 優點 | 缺點 |
|---|---|---|
| 檔名 | 簡單 | 不可控 |
| slug | SEO 佳 / 可控 | 要維護 |
✅ 總結
在 Astro 中:
👉 用 slug 控制網址的步驟:
- 在 frontmatter 加
slug - 建立
[slug].astro - 用
getStaticPaths()指定 slug
🧠 一句話記住
👉 **「網址不是檔名,而是你定義的 slug」**
如果你下一步想進階:
- 自動產生 slug(SEO friendly)
- category + slug URL 結構
- slug 變更自動 redirect
👉 這些都可以再往下優化 🚀 以上內容由 ChatGPT 產生
📖 後記
目前我的網站結構如下:
D:.
├───assets
├───components
├───content
│ └───blog
│ ├───2026032721600
│ ├───2026032743200
│ ├───2026032821600
│ ├───2026033021600
│ ├───2026033075600
│ └───ai-qna-records
├───layouts
├───pages
│ └───blog
└───styles
blog底下的資料夾,是用 自製小工具-時間戳記產生器 這篇的程式產生的。
文章的網址已經改由slug來決定,資料夾的名稱我是打算用來做文章的排序