模板有两个内容集合:blog 和 projects。字段约束写在 src/content.config.ts 里,用 Zod 校验。写错字段名或类型,构建时就会报错,而不是等到线上才发现。
文章字段
---
title: 文章标题 # 必填
description: 一句话摘要 # 必填,会用于列表和 SEO
date: 2026-08-26 # 必填
tags: # 可选,默认空数组
- Astro
- 工程实践
cover: https://example.com/cover.jpg # 可选,必须是完整 URL
draft: true # 可选,为 true 时不会构建,也不会出现在列表和 RSS 中
---
draft: true 是写到一半的文章的去处。它在开发和生产环境都会被过滤,所以可以安全地提交到仓库里。
项目字段
项目集合多了三个字段:
---
title: 项目名
description: 项目简介
date: 2026-08-20
status: 开发中 # 构思中 / 验证中 / 开发中 / 已发布 / 维护中
demoURL: https://example.com # 可选
repoURL: https://github.com/you/repo # 可选
tags:
- Tauri
- Rust
---
status 是一个枚举,值必须是上面五个之一。要改成别的措辞,编辑 src/content.config.ts 中的 z.enum([...])。
什么时候用 MDX
普通文章用 .md 就够了。需要在正文里插入组件时,把扩展名改成 .mdx,两种格式可以在同一个目录下混用。
当前这篇文章就是 MDX,所以可以直接用提示块组件:
默认样式的提示块,适合补充说明和小贴士。
type 支持 default、info、warning、error 四种。
MDX 里的组件需要在 frontmatter 之后手动 import,用 @components/ 别名即可。
代码与目录
超过两级标题的文章会自动生成右侧目录。代码块使用 Shiki 高亮,配色跟随站点的深浅色主题:
import { getCollection } from "astro:content";
const posts = (await getCollection("blog"))
.filter((post) => !post.data.draft)
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
每个代码块右上角都有复制按钮,这部分逻辑在 src/components/Head.astro 的行内脚本里,页面切换后会自动重新绑定。