先说结论
这个方案可行,而且很适合博客收藏集、友链、资源目录这类结构化内容。但推荐的链路不是“Notion Database 直接变成 Obsidian Base”,而是:Notion Database 作为录入源 → 同步为本地 Markdown → Obsidian Base 查询和管理 → Quartz 构建 HTML。Base 是视图配置,不是数据表本身。
一、为什么这个想法可行
这三个工具刚好承担不同的职责:
| 层级 | 工具 | 适合做什么 |
|---|---|---|
| 录入与运营 | Notion Database | 添加条目、修改状态、筛选、协作和批量管理 |
| 本地知识管理 | Obsidian + Base | 保存本地副本、离线检索、画廊/表格视图和双链 |
| 公开发布 | Quartz | 将 Markdown 和结构化数据构建成静态 HTML |
真正需要解决的不是“能不能同步”,而是谁是唯一数据源。如果 Notion 和 Obsidian 都可以随意修改同一个字段,很快就会遇到覆盖、重复和冲突。因此第一版应该明确:
Notion 负责录入和维护,Obsidian 负责本地镜像与展示,博客负责发布。
二、推荐的数据流
Notion Database
│
│ Notion API / 同步脚本
▼
Obsidian blog/content/collections-data/*.md
├──────────────┐
│ │
▼ ▼
博客收藏集.base Quartz 构建脚本
画廊 / 表格 / 精选 静态页面 /collections/这里有一个容易混淆的地方:.base 文件主要保存筛选、公式、字段和视图定义;它不适合作为远程数据库的承载文件。Base 查询的是本地笔记及其 frontmatter 属性,所以应该把同步结果落成 Markdown 文件,再让 Base 和 Quartz 同时读取这些文件。
三、当前 Aitiny 收藏集已经完成了什么
当前收藏集还没有接入 Notion,数据源是博客仓库中的 Markdown 文件。这其实已经是 Notion 同步方案的本地验证版:
Obsidian blog/content/collections-data/保存每一条收藏记录;- 每条记录使用 frontmatter 保存标题、类型、标签、URL、封面图、精选状态和排序值;
Obsidian blog/博客收藏集.base提供画廊、全部条目和精选视图;scripts/sync-aitiny-collections.mjs读取 Markdown 属性,生成收藏页使用的数据;content/collections/index.html是 Aitiny 风格的独立 HTML 页面;- 博客入口统一指向
/collections/,收藏页不依赖 Quartz 文章路由。
因此,未来接入 Notion 时,最稳妥的做法不是重写收藏页,而是只替换“数据进入 collections-data 的方式”。HTML 模板、Base 视图和博客入口都可以继续复用。
四、建议固定的字段
Notion Database 和本地 Markdown 应该尽量使用同一套字段。建议先保持小而稳定:
| 字段 | 用途 | 是否必填 |
|---|---|---|
notion_id | 对应 Notion 页面,作为稳定同步键 | 是 |
title | 收藏条目标题 | 是 |
collection_type | 人物、工具、Skill 等类型 | 是 |
description | 卡片简介 | 是 |
url | 原始来源或访问地址 | 建议 |
cover_url | 封面图地址 | 可选 |
tags | 标签列表 | 可选 |
featured | 是否进入精选视图 | 是 |
status | active、draft、archived | 是 |
sort_order | 页面展示顺序 | 可选 |
notion_updated_at | 最近一次 Notion 修改时间 | 是 |
其中 notion_id 很重要。标题会改,URL 也可能会改,但 Notion 页面 ID 可以作为同步脚本的唯一键。脚本每次运行时按照 notion_id 更新对应 Markdown,而不是按照标题创建新文件。
五、同步脚本应该遵守的规则
第一版建议只做 Notion → Obsidian 的单向同步,并遵守下面几条规则:
- 可重复运行:同一条记录运行多次,不产生重复文件;
- 字段白名单:只同步已经约定的字段,不把 Notion 页面内部的无关属性全部带入博客;
- 归档而不是直接删除:Notion 中归档的页面先改为
status: archived,避免误删本地记录; - 保留本地备份:同步前将
collections-data做一次 Git 提交或备份; - 先预览后发布:先执行 dry-run,检查新增、更新和归档数量,再构建博客;
- 敏感信息不落库:Notion Token、API 密钥和私有备注不能写入公开 Markdown 或前端 HTML。
如果以后希望 Obsidian 也能反向修改 Notion,那就不再是简单同步,而是双向同步系统,需要处理冲突、删除、更新时间和字段权限。当前没有必要一开始就把系统做复杂。
六、博客模块化应该怎么拆
博客不必把所有内容都当作 Quartz 文章。可以把网站拆成多个拥有独立数据、模板、样式和入口的模块:
| 模块 | 数据来源 | 公开入口 | 当前状态 |
|---|---|---|---|
| 文章 | content/**/*.md | 各文章 slug | 已稳定使用 |
| 收藏集 | collections-data/*.md | /collections/ | 已完成本地版 |
| 友链 | 友链数据或独立页面 | /friends 或兼容入口 | 正在调整 |
| 评论 | Twikoo / Giscus | 文章底部 | 已接入 |
| 导航 | Quartz 布局和 RecentNotes | 侧边栏、页脚 | 已接入 |
每个模块都可以有自己的:
- 数据结构;
- 渲染模板;
- CSS 和交互脚本;
- 构建入口;
- 无头浏览器回归测试。
这样做的好处是,收藏集换数据源不会影响评论区,评论区更换后端也不会影响文章页面。当前把“友链(暂行页面)”点击后指向 /collections/,本质上就是给旧入口增加兼容跳转,而不是把收藏集硬塞进普通文章模板。
七、Notion 接入的实际落地顺序
我建议按四个阶段推进:
阶段一:先稳定本地数据模型
继续使用当前 collections-data/*.md,把字段名称、类型和必填规则固定下来。现在就可以在 Base 里发现字段缺失、URL 不完整或封面无法访问等问题。
阶段二:增加 Notion 镜像同步
创建一个专用 Notion Database,并为它配置只读或最小权限的 Integration。同步脚本通过 notion_id 将页面属性转换为 Markdown frontmatter,先只同步新增和更新,不处理删除。
阶段三:接入博客构建
构建前执行:
Notion 拉取 → 生成 collections-data → 校验字段 → 生成 /collections/ → Quartz build本地可以手动执行,稳定后再放到 GitHub Actions 或其他构建任务中。Token 应该放在 CI 的 Secrets 中,不能写入仓库。
阶段四:再考虑双向能力
只有当你确实需要在 Obsidian 中修改后同步回 Notion,才增加反向写回。否则维持单向同步,系统更容易备份、迁移和排错。
八、需要提前注意的限制
1. Notion 图片地址不一定适合长期公开
Notion 页面中的上传图片可能带有有效期或权限限制。封面图如果要长期用于博客,最好在同步阶段复制到 Cloudflare R2 或其他稳定图床,再把稳定 URL 写入 cover_url。
2. Base 不会替你调用 Notion API
Base 可以展示本地属性,但不会自动成为 Notion 的在线客户端。同步动作必须由脚本、插件、GitHub Actions 或其他自动化任务完成。
3. 静态博客不是实时数据库
Notion 更新后,博客不会瞬间变化。它要经过同步、构建和部署,通常是几分钟级延迟。对于收藏集、友链和资源目录,这种延迟完全可以接受。
4. 公开内容必须经过筛选
Notion 中可以保留私人备注、评分、运营状态和内部链接,但同步脚本只应该输出公开字段。不要因为“Database 可以同步”就把整个数据库直接暴露到博客。
最终建议
这个方向值得做,但第一步不是立刻开发 Notion 双向同步,而是把当前收藏集的字段和模块边界稳定下来。最合适的目标架构是:
Notion 管理内容,Obsidian 保存可迁移的本地镜像,Base 管理视图,Quartz 生成页面,Cloudflare 负责发布。
这样既保留 Notion Database 的录入效率,也保留 Obsidian 的本地控制权;未来即使 Notion、Quartz 或部署平台发生变化,collections-data 仍然是可以迁移的中间层。
🔐 GitHub 评论(Giscus)
正在连接 GitHub 评论…