2026-04-27 更新:当前博客发布源目录已经收敛为 jialiang-memory/Blogs/jialiang-blog 只同步这个目录,不再同步 Knowledge/Attachments/ 或 vault 根目录的 index.md

目标

我想要的博客系统是:

  • 在 Obsidian 里写文章
  • 文件通过 Syncthing 同步到 NAS 侧的 jialiang-memory
  • 只有 Blogs/ 里的内容会被发布
  • push jialiang-memory 后自动触发博客构建
  • 最终发布到 Cloudflare Pages
  • 用自己的域名访问:jialiang-blog.cokefly.com

核心原则是:博客内容只从 jialiang-memory/Blogs/ 来,jialiang-blog 只负责构建和部署。

当前架构

Obsidian
  ↓ Syncthing 同步 Markdown 文件
NAS / 本地同步目录
  /Users/jialiang/jialiang-nas/jialiang-memory
  └── Blogs/                  # 唯一博客内容源
      ├── index.md            # 博客首页
      └── hello-world.md      # 文章
  ↓ git push
GitHub: cjl99/jialiang-memory
  ↓ trigger-blog.yml 发 repository_dispatch
GitHub: cjl99/jialiang-blog
  ↓ deploy.yml sparse checkout Blogs/
  ↓ Quartz build
Cloudflare Pages: jialiang-blog
  ↓ Custom domain
https://jialiang-blog.cokefly.com

本地路径:

/Users/jialiang/jialiang-nas/jialiang-memory
/Users/jialiang/jialiang-nas/jialiang-blog

仓库职责

仓库角色存什么
jialiang-memory内容仓库Obsidian vault,博客只取 Blogs/
jialiang-blog引擎仓库Quartz、构建脚本、Cloudflare Pages 部署流程

jialiang-memory/Blogs 是内容的唯一来源。jialiang-blog/content 是同步出来的 Quartz 输入目录,不应该手写长期内容。

Syncthing 同步

Syncthing 只负责把 Obsidian 文件同步到 NAS / 本地同步目录。它不负责发布,也不负责构建。

当前博客系统假设 Obsidian vault 最终同步到:

/Users/jialiang/jialiang-nas/jialiang-memory

推荐规则:

  • Obsidian 里写博客文章时,放进 Blogs/
  • 不要把私人笔记放进 Blogs/
  • Blogs/index.md 是博客首页
  • 文章文件名尽量用英文 slug,比如 hello-world.md
  • 文章 frontmatter 里必须有 publish: true

示例:

---
title: "Hello World"
date: 2026-04-27
tags:
  - blog
publish: true
description: "A first test post from the Blogs folder."
slug: "hello-world"
---
 
# Hello World
 
正文内容。

Cloudflare 和域名

域名 cokefly.com 的 DNS 已经交给 Cloudflare 管理。

Cloudflare Pages 项目:

jialiang-blog

Pages 默认地址:

https://jialiang-blog.pages.dev

当前自定义域名:

https://jialiang-blog.cokefly.com

这个自定义域名需要在 Cloudflare Pages 项目里绑定,同时 DNS 里有对应的 CNAME:

jialiang-blog.cokefly.com  CNAME  jialiang-blog.pages.dev

注意:不要只手动加 CNAME。Cloudflare Pages 里也必须添加 custom domain,否则可能解析到了但站点不认这个域名。

发布流程

整个流程由两个 GitHub Actions workflow 串起来。

1. jialiang-memory 触发 blog 构建

文件:

.github/workflows/trigger-blog.yml

只在 Blogs/** 有变化时触发:

on:
  push:
    branches: [main]
    paths:
      - "Blogs/**"

这样普通笔记、日记、账号资料、附件变化都不会触发博客部署。

2. jialiang-blog 构建和部署

文件:

.github/workflows/deploy.yml

收到 repository_dispatch 后,只拉取 jialiang-memory 里的 Blogs/

- name: Checkout vault
  uses: actions/checkout@v6
  with:
    repository: cjl99/jialiang-memory
    path: ./vault
    token: ${{ secrets.VAULT_TOKEN }}
    sparse-checkout: |
      Blogs

然后同步到 Quartz:

- name: Sync blog content to Quartz
  run: VAULT_PATH=./vault bash scripts/sync-blogs.sh

最后构建并部署到 Cloudflare Pages:

npx quartz build
wrangler pages deploy public --project-name=jialiang-blog --commit-dirty=true --branch=main

本地预览

jialiang-blog 仓库里运行:

cd /Users/jialiang/jialiang-nas/jialiang-blog
npm run sync:blogs
npx quartz build --serve --port 4321

然后访问:

http://localhost:4321/
http://localhost:4321/hello-world

npm run sync:blogs 会从本机的:

/Users/jialiang/jialiang-nas/jialiang-memory/Blogs

同步到:

/Users/jialiang/jialiang-nas/jialiang-blog/content

日常发布步骤

流程稳定后,日常只需要动 jialiang-memory

  1. 在 Obsidian 里新建文章到 Blogs/
  2. 确认 frontmatter 有 publish: true
  3. 等 Syncthing 同步到 NAS / 本地同步目录
  4. jialiang-memory 里提交并 push
  5. GitHub Actions 自动触发 jialiang-blog
  6. Cloudflare Pages 自动更新线上站点

常用命令:

cd /Users/jialiang/jialiang-nas/jialiang-memory
git status
git add Blogs
git commit -m "blog: add <post-name>"
git push origin main

需要的 Secrets

jialiang-memory 仓库:

BLOG_DISPATCH_TOKEN

用途:向 cjl99/jialiang-blog 发送 repository_dispatch

jialiang-blog 仓库:

VAULT_TOKEN
CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_ID

用途:

  • VAULT_TOKEN:让 blog workflow 克隆 private 的 jialiang-memory
  • CLOUDFLARE_API_TOKEN:部署 Cloudflare Pages
  • CLOUDFLARE_ACCOUNT_ID:指定 Cloudflare 账号

踩过的坑

1. Cloudflare Pages 项目要先创建

wrangler pages deploy 不会自动创建项目,需要提前在 Cloudflare Dashboard 或 API 里建好 jialiang-blog

2. Custom domain 要在 Pages 项目里绑定

jialiang-blog.cokefly.com 不能只靠 DNS CNAME。必须在 Cloudflare Pages 的 Custom domains 里添加这个域名。

3. Workflow 不能被 disable

jialiang-blogBuild and Deploy Quartz workflow 必须保持 enabled。之前 workflow 被手动 disable 后,jialiang-memory 虽然成功发了 dispatch,但 blog 没有真正部署。

4. 首页必须最终落到 content/index.md

Quartz 的首页是 content/index.md。现在首页写在 Blogs/index.md,同步脚本把 Blogs/ 内容复制到 content/ 根目录,所以最终会得到正确的首页。

5. 不要把整个 vault 复制到 Quartz

不要复制整个 jialiang-memory。那样会把账号资料、工作笔记、附件、配置文件都带进 blog 构建环境。当前方案只同步 Blogs/,并且 GitHub Actions 用 sparse checkout 限定只拉 Blogs/

6. 不要在 .gitignore 中忽略 content/

Quartz 内部会读取 .gitignore。如果写了:

content/*
!content/.gitkeep

Quartz 可能会直接扫描不到文章,构建出一个空站点。

当前规则是:jialiang-blog 保留 content/,但内容来源必须是 scripts/sync-blogs.shjialiang-memory/Blogs 同步出来的。

当前效果

线上地址:

现在这套系统的边界比较清楚:

  • Syncthing:负责文件同步
  • Obsidian:负责写作
  • jialiang-memory/Blogs:负责内容源
  • jialiang-blog:负责 Quartz 构建
  • GitHub Actions:负责自动化
  • Cloudflare Pages:负责托管
  • Cloudflare DNS:负责域名