我这次给博客补了一套分类方案:不在 frontmatter 里额外写 category,而是直接把 Obsidian 里的一级文件夹当作博客分类。
也就是说,文章放在哪里,分类就是什么。
src/content/blog/
├── 博客/
│ ├── hello-astro-obsidian.md
│ └── astro-theme-inkstone.md
├── 前端/
│ └── 前端测试.md
└── 工作/
└── work.md
上面这个结构会自动得到三个分类:博客、前端、工作。
如果一篇文章直接放在 src/content/blog 根目录,它会被归入“未分类”。这样不用为了迁移旧文章或者临时草稿额外补字段,站点也不会因为少写一个分类字段就报错。
为什么不用 frontmatter 写分类
最开始我也考虑过在每篇文章里加一个字段:
---
title: 文章标题
category: 前端
tags: [Astro, CSS]
---
这个方案很直观,但它和 Obsidian 的写作习惯有一点冲突。
我在 Obsidian 里整理文章时,文件夹本来就承担了“放在哪个抽屉里”的作用。如果再在 frontmatter 里写一遍分类,就会出现两份信息:
- 文件在
前端/目录里。 - frontmatter 里又写了
category: 前端。
短期看问题不大,时间一长就容易不一致。比如文章移动了文件夹,但忘了改 frontmatter;或者 frontmatter 改了分类,文件还留在旧目录里。分类应该是一个稳定的归档入口,不应该变成两处都要维护的重复字段。
所以最后定下来的规则是:文件夹负责分类,frontmatter 负责文章元信息,tags 负责主题关键词。
分类和标签的分工
这套博客里,分类和标签不是同一个东西。
分类更像书架上的大格子,一篇文章只有一个分类,由它所在的一级文件夹决定。比如:
博客/astro-theme-inkstone.md属于“博客”。前端/前端测试.md属于“前端”。工作/work.md属于“工作”。
标签更像便签,一篇文章可以有多个,用来描述横向主题。比如一篇文章可以属于“博客”分类,同时拥有 Astro、Obsidian、Markdown 这些标签。
这样分工以后,信息结构会清楚很多:
- 想按文章归属浏览,就看分类。
- 想按主题串联文章,就看标签。
- 想找具体内容,就用搜索。
数据层怎么判断分类
分类逻辑集中在 src/lib/posts.ts,核心思路是从文章 slug 里拆路径。
比如文章路径是:
博客/hello-astro-obsidian
拆出来的第一段是 博客,后面还有真正的文章名,所以它属于“博客”。
如果路径只有一段,比如:
hello-astro-obsidian
那说明文章在根目录,没有上级文件夹,就归入“未分类”。
为了让空分类也能出现在分类页里,代码还会扫描 src/content/blog 下的一级目录。目录名只要不是以 . 或 _ 开头,就会作为候选分类加入统计。这样以后即使某个分类暂时没有已发布文章,也能保留这个入口。
实际规则可以概括成三条:
src/content/blog下的一级文件夹名就是分类名。- 根目录文章归入“未分类”。
- 以
.或_开头的目录不作为分类,比如_templates。
页面上怎么呈现
这套分类会出现在几个地方。
首先是分类列表页:
/categories/
它展示所有分类,每个分类一行,左侧是分类名,右侧是文章数量。这里没有继续使用标签那种胶囊样式,因为分类是更稳定的导航入口,用列表会更清楚,也更适合数量增长后的阅读。
然后是分类详情页:
/categories/博客/
/categories/前端/
/categories/工作/
每个分类页会列出该分类下的文章。如果分类目录存在,但还没有已发布文章,页面会显示空状态提示。
博客首页也保留了一个轻量的分类导航。它不是完整分类页,而是一个快速入口:在文章列表上方展示“分类 / 博客 3 / 工作 1 / 前端 1”。这样读者进入博客首页后,可以直接切到自己感兴趣的分类。
文章卡片和文章详情页也会显示分类。卡片里分类跟日期放在一起,文章详情页会把分类做成可点击链接,方便从某篇文章跳回对应分类。
分类也进入搜索、RSS 和索引
分类不只是页面上的视觉入口,也会进入站点的内容索引。
搜索页会把分类加入本地搜索数据。你搜索“前端”时,不只会匹配标题、摘要和标签,也会匹配文章分类。
RSS 里也会把分类写进 category 标签,并和文章 tags 去重。这样 RSS 阅读器能读到更完整的文章归属。
同时,分类页会进入 sitemap,llms.txt 和 content-index.json 里也会输出分类信息。这些入口主要是给搜索引擎、RSS 阅读器和 AI 工具看的,让站点结构更容易被理解。
写作时怎么用
以后写文章时,我只需要先想清楚这篇文章应该放在哪个一级文件夹。
如果是博客搭建、主题改造、写作流相关,就放到:
src/content/blog/博客/
如果是前端工程、CSS、组件、性能相关,就放到:
src/content/blog/前端/
如果是工作记录、项目协作、流程复盘相关,就放到:
src/content/blog/工作/
新建分类也很简单,直接新建一个一级文件夹即可。比如以后想加“AI”分类,就创建:
src/content/blog/AI/
然后把文章放进去。只要文章不是草稿,并且有 title 和 pubDate,构建时就会自动出现在分类里。
这套方案的限制
这个方案故意保持简单,所以也有几个明确限制。
第一,一篇文章只有一个分类。它由文件所在的一级目录决定。如果一篇文章横跨多个主题,就用 tags 表达,不要再造多分类。
第二,分类名会进入 URL。比如“前端”分类的页面是:
/categories/前端/
所以重命名文件夹会改变分类 URL。以后如果分类已经被外部引用,重命名前最好补 redirects。
第三,分类的层级只取一级目录。更深的目录可以用来整理文件,但不会变成多级分类。比如:
src/content/blog/前端/CSS/某篇文章.md
它仍然属于“前端”,不会生成“CSS”这个二级分类。CSS 这种横向主题更适合放到 tags 里。
为什么我喜欢这个结果
这套方案最重要的地方不是多了一个分类页,而是把写作习惯和站点结构合在了一起。
我在 Obsidian 里移动文件,就等于调整文章分类;我在 frontmatter 里写 tags,就等于补充主题索引。分类负责归档,标签负责连接,搜索负责兜底。每一层都有自己的职责,也不会互相抢活。
对一个个人博客来说,这样已经够用了。它不复杂,也不需要后台配置;只要继续写 Markdown,站点就会自己长出分类结构。