本文说明 V7 主题的内容约定:一篇文章的元信息写在哪里、由谁校验、在什么阶段被拒绝。代码取自本仓库,可直接对照源码阅读。
内容先于页面
文章的标题、摘要和发布时间不应该只是一段随意的文本。我们为这些信息建立清晰的约定,让构建过程提前发现错误。
interface Article {
title: string;
description: string;
slug: string;
pubDate: Date;
category: 'technology' | 'journal';
tags: string[];
}
把元信息与正文分开之后,同一篇文章可以出现在首页、归档、RSS 和搜索结果里,而不需要维护几份互不一致的数据。
公开内容只有一个入口
主题的列表、详情和订阅源都从同一个公开文章函数取得数据。草稿和未来日期内容在这里被排除。
const visible = posts
.filter(({ data }) => !data.draft && data.pubDate <= now)
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
这一条是硬约束:首页、分页、分类、标签、归档、/rss.xml、站点地图与 Pagefind 索引全部读同一个结果,因此不存在「列表里看得见、直接访问却是 404」这种状态。想确认一篇草稿确实没有泄漏,只需检查这一个函数的输出。
保持 URL 稳定
文章标题可能调整,网址不应该随之改变。使用独立的 slug 可以让外部链接长期有效。
| 字段 | 用途 | 建议 |
|---|---|---|
slug | 稳定的网址 | 使用小写英文和连字符 |
category | 文章的主分类 | 一篇文章选择一个 |
tags | 更具体的主题 | 使用少量有意义的标签 |
draft | 暂不发布 | 完稿前设为 true |
文件夹只负责整理。文章放在哪一级目录,都不影响它最终的公开地址,也不影响它的分类——这两件事都只由 frontmatter 决定,所以移动文件是一次安全的操作。
把错误留在构建阶段
重复 slug、无效日期和未声明分类会中断构建。宁愿在本地修正一条数据,也不要等读者点开之后才发现页面不见了。
这套校验是刻意严格的。日期必须带明确的时区,未来日期的文章不会生成页面;引用了未声明的分类或作者同样会失败。代价是偶尔要在本地多改一行,换来的是线上不会出现半成品。