这是一篇示例文章,用来演示这个内容仓库的完整结构。你可以把它删掉,但建议先照着它抄一份骨架。
#一篇一目录
每篇文章是 posts/ 下的一个目录。目录名就是这篇文章的 slug,也就是它在网址里的那一段:
posts/content-repo-conventions/ ← 目录名 = slug = /posts/content-repo-conventions
├── index.md ← 必需,正文与 frontmatter 都在这
└── assets/ ← 本篇专属图片
├── cover-16x9.webp
└── structure-diagram.webp
两个容易踩的点:
- 目录里必须有
index.md。少了它,这篇文章会被静默跳过——不报错,URL 直接 404。这是整个结构里最难排查的一处。 - 不支持按年份分层。
posts/2026/xxx/index.md是不会被识别成文章的。想按时间组织,靠date字段,不靠目录。
#图片为什么必须用相对路径
正文里引用自己的图,只写 ./assets/...:

不写 https://...,也不写 /img/...。原因不是洁癖:
| 写法 | 问题 |
|---|---|
https://cdn.example.com/a.png | 把真相源绑死在某个 host 上。换个图床、换个域名,链接就断 |
/img/a.png | 指向站点根目录,等于假设「所有图片都堆在同一处」。文章一多就管不住 |
./assets/a.png | 跟着文章目录走。把整个目录搬到哪都还是对的 |
构建时会把 ./assets/a.png 解析成本文目录下的真实文件,读出宽高,然后把 width/height 写进渲染结果。读不出宽高就会构建失败——没有尺寸的图会造成布局跳动,这是硬拦,不是警告。
#frontmatter 字段
index.md 顶部那段 --- 之间的内容。除了 updated、cover、series 这几个可选项,其余都是必填:
| 字段 | 约束 |
|---|---|
title | 不超过 40 字 |
slug | 小写字母、数字、连字符,且必须等于目录名 |
date | YYYY-MM-DD,必须是真实存在的日期 |
category | 四选一,不能自创 |
tags | 1–4 个 |
summary | 60–120 字。列表页和搜索结果里显示的就是它 |
draft | true 不进构建。没有默认值,必须显式写 |
category 目前只有四个值:
- 工程实践
- 阅读笔记
- 生活随笔
- 工具箱
自创第五个值会让构建直接失败。要加分类,得先改校验规则,不是改文章。
#静态页与数据文件
除了文章,仓库里还有两类东西:
pages/ 扁平 .md 文件,一个文件一个页面
about.md → 网址 /about
data/ 给首页用的结构化数据
links.yaml → 友链列表
now.yaml → 首页「近况条」
pages/ 和 posts/ 的区别很重要:pages/ 是扁平文件,posts/ 是一个个目录。 把 pages/about.md 写成 pages/about/index.md,这个页面就不存在了。
#写完之后
这个仓库只负责存内容。渲染、图片处理、搜索索引都在另一个仓库里做。所以这里的检查只有一条:能不通过校验。
校验过不去,构建会当场停下,报错信息会指出是哪个文件、哪个字段、期望什么值。与其等构建报错,不如写完在本地先跑一遍校验再提交。
一句话总结:文章的目录名就是它的网址,图片跟着目录走,frontmatter 写错就构建失败。 记住这三条,这个结构就不会用错。