多源内容聚合发布架构:将 Obsidian 手动创作与 AI 自动生成的内容统一汇聚,通过 CI 自动编译部署为静态站点。

    [Obsidian Vault]           [AI Agent]
          │                        │
          ▼                        ▼
   [sync_manager.py]     content/ai-agent/
          │                        │
          ┌────────┬───────────────┘
          ▼        ▼
    ┌──────────────────────────────┐
    │     [本地 Quartz 仓库]        │
    │  content/obsidian/  ← rsync  │
    │  content/ai-agent/  ← rsync  │
    └──────────────┬───────────────┘
                   │
             git push
                   ▼
         [Gitee CI 流水线]
         npm install → npx quartz build
                   │
             rsync (SSH)
                   ▼
         [云主机 Docker+Nginx]
         /data/website/site/

数据流经三个阶段:Markdown → 本地聚合 → CI 编译为静态文件 → 分发到云主机托管。具体步骤见 §2。


1. 目录结构

1.1 Obsidian Vault(编排侧)

脚本和数据源同位,编排工具归入 Obsidian Vault 的 _Agent/_发布/:

Obsidian Vault/
├── _Agent/
│   └── _发布/
│       ├── sync_manager.py      # 同步编排脚本(git 跟踪)
│       └── pyproject.toml       # Python 依赖声明(git 跟踪)
├── .gitignore                   # 屏蔽 _Agent/_发布/.venv/
└── ...                          # 知识库正文

pyproject.toml 极简模板:

[project]
name = "quartz-sync"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []  # 按需添加

运行方式:uv run _Agent/_发布/sync_manager.py,uv 自动管理虚拟环境,无需手动创建。

1.2 Quartz 仓库(构建侧)

在 Quartz 仓库的 content/ 下实施命名空间隔离。每个源独占子目录,rsync --delete 的作用域被限制在对应子目录内,防止跨源同名文件互相覆盖/删除:

quartz-repo/
├── content/
│   ├── obsidian/          # Obsidian 同步区(rsync --delete 仅影响此目录)
│   ├── ai-agent/          # AI 自动化生成区
│   └── index.md           # 手动维护的聚合首页
├── quartz.config.ts       # 渲染配置
└── package.json           # 项目定义

注:rsync --delete 会删除目标目录中源目录不存在的文件。确保 Obsidian Vault 删除笔记后,同步也会清理对应文件。

原则:Quartz 仓库 = 纯构建。 只存框架代码 + 内容 + 配置,不放任何编排工具。


2. 工作流详解

第一阶段:本地聚合

职责:sync_manager.py(位于 Obsidian Vault _Agent/_发布/)将多源内容镜像到 Quartz 仓库并提交。

运行方式:

cd <Obsidian_Vault_Path>
uv run _Agent/_发布/sync_manager.py

脚本执行步骤:

  1. rsync -av --delete <Obsidian_Path>/ <Quartz_Path>/content/obsidian/
  2. rsync -av --delete <AI_Output_Path>/ <Quartz_Path>/content/ai-agent/
  3. 自动执行 git add . && git commit -m "site update" && git push

异常处理:sync_manager.py 应具备断点续传和错误重试能力。建议对每个 rsync 源做容错,单个源同步失败不阻塞其余源。

第二阶段:云端构建与部署

职责:Gitee Go 流水线,编译静态站点并分发到云主机。

  1. 触发:Quartz 仓库接收到 Push
  2. 构建:检出代码 → npm install → npx quartz build
  3. 分发:将 public/ 增量同步到云主机 /data/website/site

流水线配置:CI 定义在仓库的 .workflow/ 目录中(参考已有配置)。关键前提:流水线需通过 SSH 密钥免密 rsync 到云主机,需在 Gitee 项目设置中配置部署密钥。详见 Gitee Go 文档。


3. 设计决策

  • 内容与代码分离:Obsidian 环境保持纯净,无程序文件;Quartz 仓库仅作为聚合中间层。代价:本地需维护一个完整的 Quartz 仓库,占用额外磁盘空间。
  • 脚本与构建分离:编排工具(sync_manager.py)不进 Quartz 仓库,存放在 Obsidian Vault 的 _Agent/_发布/。好处:Quartz 升级框架时零干扰,脚本迭代与框架升级完全解耦。
  • 命名空间隔离:每个内容源独占子目录,即使某一来源格式出错也只影响该子目录,不会拖垮全站。代价:Quartz 前端路由需适配子目录层级(如 content/obsidian/ 下的页面路径)。
  • 扩展性:新增”内容来源 3”只需在 content/ 下新建目录并修改同步脚本,其余环节无需改动。代价:CI 编译时间随内容量线性增长,大量笔记时构建等待时间较长。

4. 实施清单

  1. 在 Quartz 仓库创建 obsidian 和 ai-agent 占位目录。
  2. 配置 quartz.config.ts 中的主页逻辑(确保 index.md 能够展示这些目录)。
  3. 在 Obsidian Vault 创建脚本目录:_Agent/_发布/,放入 sync_manager.py 和 pyproject.toml。
  4. 在 Obsidian Vault 的 .gitignore 中添加 _Agent/_发布/.venv/。
  5. 编写 sync_manager.py 同步逻辑并测试 uv run。
  6. 配置 Gitee 流水线(.workflow/),确保 CI 可通过 SSH 免密 rsync 到云主机。
  7. 云主机部署 Docker + Nginx,指向 /data/website/site 目录。

5. Quartz 升级指南

你的 quartz-repo 基于官方仓库 fork,升级时需合并上游更新同时保留自定义配置。推荐 rebase 模式:

upstream → 官方仓库(需添加为远程)
origin → 你 fork 的仓库(默认远程)

升级步骤:

# 1. 暂存所有变更(含自定义配置 + content/)
git stash
 
# 2. 拉取官方最新代码
git fetch upstream
 
# 3. rebase 到官方最新版本
git rebase upstream/main   # 主分支名视官方而定
 
# 4. 解决冲突(通常只有 quartz.config.ts 等配置文件)
# 5. 恢复 content/ 目录
git stash pop
 
# 6. 强制推送(rebase 后历史不同步)
git push origin main --force

注意事项:

  • content/ 是自动管理的,永远不需要 rebase。冲突时只需在 stash pop 后确认内容一致。
  • quartz.config.ts 等配置冲突是预期的,说明上游改了配置字段,需手动对比保留。
  • 后续不要在 content/ 下手动编辑非聚合文件(除 index.md),否则每次升级都可能冲突。
  • 如果升级频率很低或不想处理冲突,可 git push 后 rm -rf 重新 clone 仓库,再运行 sync_manager.py 恢复内容。