这篇指南写给所有想在这个博客框架上发文章的人——包括未来的我自己。
本站基于 Astro + AstroPaper 主题搭建,文章的编写方式非常简单:本质上你只需要新建一个 .md 或 .mdx 文本文件,填写一段 YAML 格式的「frontmatter」作为元信息,然后用 Markdown 写正文。剩下的排版、目录、搜索索引、分享卡片,都由框架自动处理。
下面从「文章放哪里」开始,一步步讲清楚。
Table of contents
Open Table of contents
文章放在哪里
所有文章都存放在 src/content/posts/ 目录下。本站的约定是:一篇文章 = 一个文件夹,正文固定叫 index.mdx,配图放在同目录的 assets/ 里随文章一起走:
src/content/posts/
├── _20260909-1/ ← 文件夹 = 发布时间(当天第一篇,序号 1)
│ └── index.mdx
├── _20260909-2/
│ ├── index.mdx ← 正文(.mdx 或 .md 均可)
│ └── assets/ ← 这篇的配图(没图可以省略)
└── _20260909-3/
├── index.mdx
└── assets/
├── IVF1.png
└── HNSW.png
.md:纯 Markdown,适合绝大多数普通文章.mdx:在 Markdown 基础上允许引入组件(比如表格组件、Astro 图片组件),需要更强排版能力时用- 文件夹统一
_开头,命名规则是_YYYYMMDD-N:日期精确到日;同一天有多篇时N从 1 开始接力(1、2、3…),自动用pnpm new post创建即可,不用手工数 - 新增一篇 =
pnpm new post(见下文);删除一篇 = 删掉整个文件夹,不留孤儿图片
为什么文件夹要 _ 开头?_ 开头的目录里的文件照常发布,但目录名不会进入链接;_ 开头的文件则完全不会发布(适合随手放草稿)。所以链接永远只由 slug 决定,不会混进文件夹名。想让文章彻底不发布,把它移出 posts 集合(比如放进 src/content/archive/),或者加 draft: true。
文章链接由什么决定
文章的 URL 完全由 frontmatter 里的 slug 字段决定,与文件路径、文件名无关:
slug就是 URL 中/posts/后面的一段,本站默认写成YYYYMMDD-N(与文件夹同名),例如slug: 20260909-1→/posts/20260909-1- 因为正文文件统一叫
index.mdx,slug 是必填字段——同一目录下多个index.mdx若不写 slug,会因 id 相同而无法构建 - 一旦发布,链接就不建议再改(会变 404);想用更好记的词的可以发布前替换成短词,中文也支持:
slug: 向量数据库索引→/posts/向量数据库索引 - slug 全站唯一;页面显示的标题来自
title,与 slug 无关
Frontmatter:文章的「身份证」
Frontmatter 是文件最顶部用 --- 包裹的一段 YAML,存放文章的所有元信息。它会被用于列表卡片、SEO、分享卡片、RSS 等几乎所有需要展示文章信息的地方。
以下是本站支持的全部字段:
| 字段 | 说明 | 备注 |
|---|---|---|
| title | 文章标题,同时作为页面 h1 | 必填 |
| slug | 文章链接标识,即 URL 中 /posts/ 后面的一段 | 必填 |
| description | 文章摘要,用于列表卡片和 SEO 描述 | 必填 |
| pubDatetime | 发布时间,ISO 8601 格式 | 必填 |
| modDatetime | 修改时间,ISO 8601 格式,只有文章被修改过才加 | 可选 |
| author | 作者名 | 默认取站点配置的作者(Akatshi) |
| featured | 是否在首页「精选」区域展示 | 默认 false |
| draft | 是否为草稿(草稿不会出现在任何页面) | 默认 false |
| tags | 标签列表,YAML 数组格式 | 默认 others |
| ogImage | 社交分享卡片图,可以是远程 URL 或相对路径 | 可选;不填则自动生成 |
| canonicalURL | 规范链接,若文章已发布在其他地方用 | 可选 |
| hideEditPost | 隐藏这篇文章标题下方的「编辑本文」按钮 | 可选,默认 false |
| timezone | 仅对本文生效的时区(IANA 格式),覆盖站点全局时区 | 可选,默认 Asia/Shanghai |
其中 title、slug、description、pubDatetime 四项是必填的。title、slug 和 description 对 SEO 和卡片展示很重要,请务必认真填写,不要偷懒。
如何快速拿到 ISO 8601 时间?在浏览器控制台运行 new Date().toISOString(),或者直接执行 date -u +%Y-%m-%dT%H:%M:%SZ。
一个标准的 frontmatter 示例
---
title: 文章的中文标题
slug: 20260909-4 # 默认是日期码;发布前想换成更好记的词也随时可以(中英文都支持)
author: Akatshi # 不填则默认是站点作者
pubDatetime: 2026-09-09T10:30:00+08:00
modDatetime: 2026-09-10T21:00:00+08:00 # 修改过文章再补上
featured: false
draft: true # 草稿阶段写 true,发布前改成 false
tags:
- guide
- blog
description: 一句话说清这篇文章讲什么,会出现在列表卡片和搜索引擎摘要里。
---src/content/posts/_20260909-4/index.mdx
- 填未来的时间,文章会被视为「定时发布」:到点之前读者看不到,只有你可以通过本地开发模式预览
- 列表排序按
modDatetime(若有)否则pubDatetime倒序,所以改完文章记得更新 modDatetime,否则它会被挤到列表下方
正文的排版语法
正文就是 Markdown。这里列几个本站写作时最常用的要点,也相当于一个快速备忘录。
标题层级:h1 留给 title
页面的大标题(h1)已经由 frontmatter 的 title 输出了,所以正文里的章节标题请从 ##(h2)开始,最多用到 ######(h6)。这既是视觉规范,也有利于 SEO 和阅读器无障碍体验。
## 二级标题:章节
### 三级标题:小节
常用行内与段落语法
**加粗**、*斜体*、~~删除线~~、`行内代码`、[超链接](https://example.com)
- 无序列表项
- 无序列表项
1. 有序列表项
2. 有序列表项
> 引用别人的话,或强调一段观点。
---
用一条分隔线把两个大段落隔开,也是不错的结构手法。
代码块与语法高亮
代码块用三个反引号包裹并标注语言,本站使用 Shiki 做高亮,支持文件标题、增删标记、关键词高亮等增强语法。这也是写作技术类文章最常用的功能:
function greet(name: string) {
return `Hello, ${name}!`;
}
const message = greet("世界");
const oldMessage = "你好";examples/hello.ts
上面这段代码块本身就用到了三种标记:// [!code ++] 绿色新增行、// [!code --] 红色删除行、// [!code highlight] 高亮当前行。在代码块第一行反引号后写 file="路径/文件名.ts" 即可显示文件标题栏。
Callout:带图标的提示块
想在正文中插入醒目的提示、警告或小贴士?本站支持 Obsidian 风格的 callout,写法是「blockquote + 类型标记」,正文中渲染为带图标和底色的小卡片:
补充性说明,读者应该留意但不必紧张。
实用的建议、快捷键或最佳实践。
需要特别强调的关键信息。
可能出错或有副作用的事情。
有严重风险,可能导致数据丢失或行为错误。
语法来源也很直观:
> [!TIP]
> 提示内容写在这一行。
还可以自定义标题、或者做成可折叠的:
类型标记后面跟的文字会变成卡片标题。不写的话默认用类型名。
默认折叠的警告
加上 - 之后默认收起,读者点开才看得到,适合放很长但不打断阅读的补充说明。
> [!NOTE] 自定义标题
> 类型后跟的文字即标题。
> [!WARNING]- 默认折叠
> `-` 表示默认收起,`+` 表示默认展开但可收起。
本站支持的 callout 类型还包括 ABSTRACT、INFO、TODO、SUCCESS、QUESTION、FAILURE、BUG、EXAMPLE、QUOTE 等,每种都有对应图标与颜色。一般记住上面五种就够用了。
插入目录
默认情况下文章不会自动生成目录。想加目录,就在想让目录出现的位置写一行固定的二级标题:
## 开头的内容
## Table of contents
## 正文第一个章节
注意 ## Table of contents 这行必须一字不差用英文写(它是处理管线的触发词)。构建后它会变成一个可展开的「目录」列表,自动收集你正文中后面的标题。目录适合长文,短文不写也没关系。
图片怎么放
图片有三种存放方式,取舍在于「要不要自动优化」以及「要不要跟文章放一起」:
方式一:放在文章自己的 assets/(推荐)
配合前面「一篇一文件夹」的约定,配图放进正文旁的 assets/ 子目录,在 .mdx 正文里用相对路径直接引用。构建时 Astro 会把它们当作可优化资源自动处理(压缩、加 hash、适配格式),这是本站文章配图最常用的方式:
src/content/posts/_20260909-3/
├── index.mdx
└── assets/
├── IVF1.png
└── HNSW.png

相对路径以 index.mdx 所在目录为基准,所以 assets/IVF1.png 就能指到上面的图。图随文走,删文章时整个文件夹一起删,不会留孤儿图片——每篇都带图的场景强烈推荐这种。
方式二:放在 src/assets/(多篇文章复用,自动优化)
适合多篇共用或用于站点公共位置的图片。放进 src/assets/ 后,在 .mdx 里通过 @/assets 别名导入,用 <Image> 组件渲染,Astro 会做压缩、尺寸适配和格式转换:
import { Image } from "astro:assets";
import exampleImg from "@/assets/images/example.jpg";
<Image src={exampleImg} alt="一张经过优化的图片" />
方式三:放在 public/(不优化,仅简单直接)
把图片丢进 public/images/,用绝对路径引用即可。Astro 不会做任何处理,原样输出,适合已经压好、偶尔一用的图:

无论哪种方式,上传前都建议先用 TinyPNG 之类的工具压缩一遍。尤其是 public/ 目录里的图片,未经优化会明显拖慢页面。正文配图请克制,少而精。
草稿与预览流程
写作时最舒服的工作流是这样的:
- 复制一个已有 post 或按上面的 frontmatter 模板新建文件,先把
draft: true写上 - 运行
pnpm dev,在http://localhost:4321实时预览——开发模式下草稿和未到发布时间的定时文章对你都是可见的,方便边写边检查排版 - 写完检查无误后,把
draft改成false(或删掉),提交推送
pnpm new post # 生成新文章骨架(按当天日期 + 顺序码命名,draft: true)
pnpm dev # 本地开发预览
pnpm sync # 改动内容 schema 后重新生成类型
pnpm build # 类型检查 + 构建 + 生成 Pagefind 搜索索引
pnpm preview # 本地预览生产构建
站点搜索依赖 Pagefind 索引,而它是在 pnpm build 阶段生成的。所以部署前请务必执行一次 pnpm build,否则新文章搜不到。
一篇完整文章的模板
步骤:新建一篇
- 运行
pnpm new post(想顺便带标题可以写成pnpm new post "文章标题"),脚本按当前日期自动接力生成骨架:
src/content/posts/
├── _20260909-1/ ← 当天第一篇是 1
├── _20260909-2/
├── _20260909-3/
└── _20260909-4/ ← 新创建的会接着排 4、5、6…,不用手动数
├── index.mdx ← 含草稿模板,frontmatter 已自动填好时间与 slug
└── assets/ ← 空的,配图放这里
pnpm new post已把slug默认填成20260909-4这种日期码(URL:/posts/20260909-4),直接发布也可以;想更好记就发布前替换成短词,中英文都行(中文 slug 本站已验证可用):
slug: 向量数据库索引 # -> /posts/向量数据库索引
# 或
slug: rag-retrieval # -> /posts/rag-retrieval
- 写正文;配图放进
assets/,按上面「方式一」用引用 - 写完预览无误后,把
draft改成false即可发布
下面是一份参考模板(pnpm new post 生成的文件结构与此相同):
---
title: 这里是文章标题
slug: 20260909-4 # 自动生成;发布前想换成易记的词也行,中英文都支持
description: 一句话摘要,会显示在列表卡片和搜索结果里。
pubDatetime: 2026-09-09T10:30:00+08:00
featured: false
draft: true # 写完后改成 false
tags:
- guide
- blog
---
开场白:用两三句话说清楚这篇文章要解决什么问题,给读者一个继续读下去的理由。
## Table of contents
## 第一个小节
正文内容。段落之间用空行隔开,一段只讲一件事。
### 如果需要,可以再分小标题
> [!TIP]
> 关键经验用 callout 强调,比大段加粗文字更好读。
## 结尾
用一两句话总结全文,并给出下一步行动建议。如果参考了他人的文章或项目,记得在这里附上链接致谢。
写作的几条朴素建议
最后分享几条我自己的写作习惯,供参考:
- 摘要要认真写:
description会出现在首页卡片、搜索页和社交分享里,它是读者决定点不点进来的关键 - 每段只讲一件事:Markdown 里空行分隔的段落,本质是帮读者控制呼吸节奏;一段超过五六行就考虑拆开
- 善用 callout 而非堆砌:加粗、引用、callout 都用一点文章会很花哨;把强调手段留给真正重要的内容
- 图文并茂但克制:没有配图不是问题,插图一定要和文字强相关
- 写完回头改一次:文章发布前至少通读一遍,顺手把
modDatetime更新掉
写完这篇文章本身,就是一次很好的实践——你现在看到的所有排版元素(目录、callout、代码高亮、表格),都来自上面的语法。如果还有哪里不清楚,翻一翻 src/content/posts/ 里其他示例文章的源码,是最好的参考。