写一篇:博客与 Frontmatter
这个站点的文章怎么来的:把 .md 丢进 /p、在 sk.json 加一行,然后正文顶上写一段 frontmatter。标题、日期、标签、摘要都在那里,页面、订阅源和搜索引擎读的都是同一份。
这个站点对外就是一份博客:JinSuper 奇思妙想。
写一篇不是「填后台表单」,是往 /p/ 丢一个 Markdown 文件 —— 然后正文顶上写一段头信息。
三十秒上手#
- 把
.md放进/p/(可以带子目录,比如/p/idea/) - 在
/sk.json里加一行:分组 → 标题 → 相对/p/的路径 - 正文最上面写一段 frontmatter(本文开头那段就是)
- 刷新阅读器就能看见;要让搜索引擎也看到独立网址(以及出现在博客首页的时间线里),跑一次构建
{
"奇思妙想": {
"枣香童年": "idea/3.枣香童年.md"
}
}
Frontmatter 写什么#
文件必须以第一行的 --- 开头,再以单独一行的 --- 收尾。中间是「键: 值」:
---
title: 枣香童年
date: 2026-10-06
updated: 2026-10-07
author: JinSuper # 多个作者写 [JinSuper, ABC]
category: 奇思妙想
tags: [随笔, 童年]
summary: 爷爷的红枣饼干齁得恰到好处。
---
| 字段 | 作用 |
|---|---|
title |
文章标题。阅读器顶栏、浏览器标签、搜索结果里显示的都是它;写了它,正文开头那行一模一样的 # 标题 会自动去掉(免得一页两个标题) |
date |
发布日期,2026-10-06 或 2026.10.6 都认,写进 sitemap 的 lastmod、RSS 的 pubDate 和结构化数据 |
updated |
最后修改日期,填了就多显示一枚「更新于」 |
author |
作者,默认 JinSuper(写在 site.json 的 blog.author 里)。单个作者写 author: JinSuper,多个写 author: [JinSuper, ABC] —— 会画成多枚,也分别进 RSS 与结构化数据 |
category |
分类,显示成标签行里的一枚 |
summary |
摘要 / 一句话简介,进 <meta name="description">、Open Graph 与 RSS |
tags |
标签,写成 [随笔, 童年] 或者一行一个 -。标签在页面上是可点的:指向博客首页的标签筛选 |
toc |
写 toc: true 在正文开头再插一份目录(默认不插:阅读器与文章页都已有侧栏目录) |
其余键不会丢:已知的排成上面那样,不认识的照样列在元数据卡片的下半部分,
写成什么样就显示成什么样。
不打算发出去的稿子,在 frontmatter 里写 draft: true(或者 nopage: true):
它会留在清单里、读得到,但不会生成独立文章页,也不进订阅源和 sitemap。
目录#
目录不用你操心,两处都是自动的:
- 阅读器(
/p/docs.html):左边栏一份「本页目录」,嵌在页面里跟着一起滚,高亮当前小节 - 文章页(
/p/post/…):文章左侧一列目录,跟随阅读高亮当前小节。
一节也算,每篇都有:通篇没有小标题的短文(随笔那种)会退回一条「文章标题」兜底
层级按相对级别缩进(文档里最浅的一级算第一层,标题写在 frontmatter 里时正文从 h2 起也算第一层),
所以缩进和文章结构对得上,不会整份目录平白缩一格。
想在正文开头再摆一份,frontmatter 写 toc: true(或者自己写 [[toc]],放在你想放的位置)。
构建之后多了什么#
跑一次 node build/build.mjs(或 部署.cmd build),除了阅读器还会产出:
| 产物 | 是什么 |
|---|---|
/p/index.html |
博客首页:最新几篇、标签筛选、完整时间线(列表全是构建期渲染的静态 HTML)。「最新」只放活稿,时间线与标签里归档稿也一起列(带「归档」徽标,标签栏里点「归档」能只看归档) |
/p/post/<路径>.html |
每篇文章一个独立网址,服务端渲染好的正文 + 元数据卡片 + 上下篇 |
/p/feed.xml |
RSS 2.0 订阅源,最新 30 篇 |
/p/docs.html |
阅读器本身,标题、描述、canonical、结构化数据都跟着 site.json 的 blog 段走 |
sitemap.xml 里会带上每篇文章的独立地址和 lastmod,
robots.txt 对主流搜索引擎与 AI 抓取一律放行。
三条老规矩(别踩)#
- 相对路径按
/p/算:正文里写pic/a.png,指的是/p/pic/a.png。构建期会自动补成文章页能用的前缀。 - 不引外链、不用 base64:这是托管平台的硬规则,图片、字体都放站点里。
- 文件名里的中文要编码:写链接时用
%E6%9E%A3...,别指望浏览器猜。
归档稿#
发布控制台可以把一篇 Markdown 烘成静态 HTML,放进 /p/archive/(原文留底到项目根的 para/)。
归档稿是成品:阅读器直接注入正文,不再走浏览器端渲染器;它也是能独立打开的页面,
所以控制台的产物外壳同样会写 canonical / OG / JSON-LD —— 元数据一样取自源文件的 frontmatter。
几条差别记一下:
- 归档稿不会被藏起来:博客首页的时间线里照样列(带一枚「归档」徽标),
标签栏里也有一枚「归档」可以只看归档;只有「最新」那几张卡片只放活稿 - 归档稿的外壳和文章页是同一套:站点顶栏、左侧「本页目录」(每篇都有,短文也有兜底那一条)、
上下留白都一样(样式 / 脚本 / 骨架都来自build/lib/chrome.mjs那一份) - 归档稿不会再有
/p/post/那套独立文章页(它本身就是一份独立页面) - 同一篇既有活着的正文、又有归档稿时,在归档稿源文件的 frontmatter 里写一行
canonical: /p/post/…指过去,搜索引擎就不会把它当成第二份内容
想让一篇稿子回到「活文章」的状态,把 Markdown 放回 /p/ 并在 sk.json 里登记即可。