把 Obsidian 文件夹变成博客分类

我这次给博客补了一套分类方案:不在 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 属于“工作”。

标签更像便签,一篇文章可以有多个,用来描述横向主题。比如一篇文章可以属于“博客”分类,同时拥有 AstroObsidianMarkdown 这些标签。

这样分工以后,信息结构会清楚很多:

  • 想按文章归属浏览,就看分类。
  • 想按主题串联文章,就看标签。
  • 想找具体内容,就用搜索。

数据层怎么判断分类

分类逻辑集中在 src/lib/posts.ts,核心思路是从文章 slug 里拆路径。

比如文章路径是:

博客/hello-astro-obsidian

拆出来的第一段是 博客,后面还有真正的文章名,所以它属于“博客”。

如果路径只有一段,比如:

hello-astro-obsidian

那说明文章在根目录,没有上级文件夹,就归入“未分类”。

为了让空分类也能出现在分类页里,代码还会扫描 src/content/blog 下的一级目录。目录名只要不是以 ._ 开头,就会作为候选分类加入统计。这样以后即使某个分类暂时没有已发布文章,也能保留这个入口。

实际规则可以概括成三条:

  1. src/content/blog 下的一级文件夹名就是分类名。
  2. 根目录文章归入“未分类”。
  3. ._ 开头的目录不作为分类,比如 _templates

页面上怎么呈现

这套分类会出现在几个地方。

首先是分类列表页:

/categories/

它展示所有分类,每个分类一行,左侧是分类名,右侧是文章数量。这里没有继续使用标签那种胶囊样式,因为分类是更稳定的导航入口,用列表会更清楚,也更适合数量增长后的阅读。

然后是分类详情页:

/categories/博客/
/categories/前端/
/categories/工作/

每个分类页会列出该分类下的文章。如果分类目录存在,但还没有已发布文章,页面会显示空状态提示。

博客首页也保留了一个轻量的分类导航。它不是完整分类页,而是一个快速入口:在文章列表上方展示“分类 / 博客 3 / 工作 1 / 前端 1”。这样读者进入博客首页后,可以直接切到自己感兴趣的分类。

文章卡片和文章详情页也会显示分类。卡片里分类跟日期放在一起,文章详情页会把分类做成可点击链接,方便从某篇文章跳回对应分类。

分类也进入搜索、RSS 和索引

分类不只是页面上的视觉入口,也会进入站点的内容索引。

搜索页会把分类加入本地搜索数据。你搜索“前端”时,不只会匹配标题、摘要和标签,也会匹配文章分类。

RSS 里也会把分类写进 category 标签,并和文章 tags 去重。这样 RSS 阅读器能读到更完整的文章归属。

同时,分类页会进入 sitemap,llms.txtcontent-index.json 里也会输出分类信息。这些入口主要是给搜索引擎、RSS 阅读器和 AI 工具看的,让站点结构更容易被理解。

写作时怎么用

以后写文章时,我只需要先想清楚这篇文章应该放在哪个一级文件夹。

如果是博客搭建、主题改造、写作流相关,就放到:

src/content/blog/博客/

如果是前端工程、CSS、组件、性能相关,就放到:

src/content/blog/前端/

如果是工作记录、项目协作、流程复盘相关,就放到:

src/content/blog/工作/

新建分类也很简单,直接新建一个一级文件夹即可。比如以后想加“AI”分类,就创建:

src/content/blog/AI/

然后把文章放进去。只要文章不是草稿,并且有 titlepubDate,构建时就会自动出现在分类里。

这套方案的限制

这个方案故意保持简单,所以也有几个明确限制。

第一,一篇文章只有一个分类。它由文件所在的一级目录决定。如果一篇文章横跨多个主题,就用 tags 表达,不要再造多分类。

第二,分类名会进入 URL。比如“前端”分类的页面是:

/categories/前端/

所以重命名文件夹会改变分类 URL。以后如果分类已经被外部引用,重命名前最好补 redirects。

第三,分类的层级只取一级目录。更深的目录可以用来整理文件,但不会变成多级分类。比如:

src/content/blog/前端/CSS/某篇文章.md

它仍然属于“前端”,不会生成“CSS”这个二级分类。CSS 这种横向主题更适合放到 tags 里。

为什么我喜欢这个结果

这套方案最重要的地方不是多了一个分类页,而是把写作习惯和站点结构合在了一起。

我在 Obsidian 里移动文件,就等于调整文章分类;我在 frontmatter 里写 tags,就等于补充主题索引。分类负责归档,标签负责连接,搜索负责兜底。每一层都有自己的职责,也不会互相抢活。

对一个个人博客来说,这样已经够用了。它不复杂,也不需要后台配置;只要继续写 Markdown,站点就会自己长出分类结构。