用 Pi 从零搭建个人知识库:Quartz + PARA + PWA 全流程实录

用 Pi 从零搭建个人知识库:Quartz + PARA + PWA 全流程实录

Author: tengdy | Create: 2026-08-27 21:10:34 | Update: 2026-08-28 20:33:15 | 分类:知识库与 RAG

PiObsidianPARA第二大脑AI编程知识库

三个月前我还在用 Obsidian 散装记笔记,现在我已经有了一个跑在本地、可离线打开、界面精美、还能装成桌面应用的私人知识库——ReverieVault

整个过程全部由 AI 编程助手 Pi 协助完成,从零开始,没写一行前端代码。这篇文章记录完整的搭建过程、踩过的坑和最终沉淀的方法论,希望能帮你少走弯路。


一、为什么不用现成的知识库工具?

我的需求其实很朴素:

  • 内容是我的一手资料(项目文档、研究笔记、随手记录),不是给别人看的博客
  • 要能本地离线访问,不要依赖云端服务
  • 要有自己的风格,不是千篇一律的模板
  • 要能装成应用,像原生软件一样双击打开

市面上的方案: - Notion / 语雀:云端,数据不在自己手里 - Obsidian 发布:付费,且样式定制有限 - Hugo / Jekyll:太"博客",知识库的组织能力弱 - 自己写:成本太高

最后选中了 Quartz——一个把 Markdown 笔记变成静态网站的工具。它有几个杀手级特性:

  1. 原生支持双向链接[[wikilink]]),Obsidian 用户的笔记直接可用
  2. 内置搜索 + 知识图谱,知识库的灵魂功能
  3. 861 个 Obsidian 社区主题,想要什么风格都有
  4. SPA 架构,页面切换无刷新,体验接近原生应用

二、搭建:从源码开始(避开 create-quartz 的坑)

Quartz v5 官方推荐用 npx create-quartz@latest 脚手架,但我执行时发现 npm 仓库里没有这个包(v5 只提供了 GitHub 源码)。所以走了源码路线:

git clone https://github.com/jackyzha0/quartz.git yeatlib-temp
cd yeatlib-temp && npm install

然后手动配置。Quartz v5 的配置是 YAMLquartz.config.yaml),不是 v4 的 TypeScript——这点和网上大部分教程不一样,别搞混。

端口和本地服务

npx quartz build --serve --port 9796 --watch

--watch 模式下改任何 Markdown 自动重建,浏览器即时刷新,体验和 Obsidian 预览几乎一样。

三、内容组织:PARA 管素材,Wiki 管知识

这是我最得意的一层设计。知识库内容怎么组织,决定了它会不会变成一个"电子垃圾堆"。

我采用了 Tiago Forte 的 PARA 方法 + Andrej Karpathy 的 LLM Wiki 理念 的双层结构:

content/
├── 01-Projects/     # 进行中的项目(有截止日期的事)
│   ├── 一叶知秋/     # 孩子的教育规划
│   ├── 如登博客/     # 博客运营
│   └── 国庆骑行/     # 父子骑行计划
├── 02-Areas/        # 持续关注的领域(没有截止日期)
│   ├── 宇宙/
│   ├── 哲学/
│   └── AI/
├── 03-Resources/    # 可复用素材(工具、模板、参考)
├── 04-Archives/     # 归档(已结束的事)
└── 05-Wiki/         # 知识提炼层

核心思想:01-04 是 Raw 层(一手资料),05 是 Wiki 层(提炼后的知识)。

  • Raw 层:按 PARA 的"可行动性"组织——正在做的项目最优先(01),其次是长期关注的领域(02),再是可复用的素材(03),最后是归档(04)
  • Wiki 层:从 Raw 里提炼出可复用的知识条目,双向链接回来源。比如"国庆骑行"项目的经验 → 提炼成「长途骑行准备清单」Wiki 条目;博客草稿 → 提炼成「Harness / Agent / MCP 概念卡」

数据流是单向的:Raw 素材 → 提炼 → Wiki 条目。Wiki 只放"值得长期记住、可以被 AI 消费"的结构化知识,避免 Wiki 层变成第二个垃圾堆。

数字前缀(01-05)保证侧边栏顺序永远符合优先级,这是 PARA 在文件系统层面的落地。

四、主题与字体:861 个主题随便挑

Quartz v5 通过 @quartz-themes/core 插件加载 861 个 Obsidian 社区主题,而且支持"混搭"——可以只拿某个主题的表格样式、另一个主题的代码块样式。

plugins:
  - source: "@quartz-themes/core"
    enabled: true
    options:
      theme: minimal        # 主题名
      mode: both            # 亮色+暗色都支持

主题包需要预装(直接 npm install,否则构建时会自动安装但可能踩依赖冲突):

npm install @quartz-themes/minimal --legacy-peer-deps

我实测了 15 个主题(Tokyo Night、Catppuccin、Everforest、Nord、Monokai……)后选了 minimal——极简、内容优先,适合大量阅读的知识库场景。

字体踩坑记录

中文知识库的字体选择是个大学问。Google Fonts 上可用的中文字体有限,我试了:

  • 站酷小薇(ZCOOL XiaoWei):标题很有书卷气,和"锁梦斋"的气质绝配 ⭐
  • 思源黑体(Noto Sans SC):正文首选,清晰不疲劳
  • 马善政毛笔 / 青刻黄油:个性十足但偏装饰

踩坑:站酷小薇只有 400 一个字重,而 Quartz 默认给标题请求 400+700,导致 Google Fonts 返回 400 错误、字体加载失败。解决:配置里显式指定字重:

typography:
  header:
    name: "ZCOOL XiaoWei"
    weights: [400]     # 关键:只请求存在的字重
  body: "Noto Sans SC"

五、本地应用化:PWA 的正确姿势

这是折腾最久的部分。我最初做了一个 macOS .app 包装(Chrome --app 模式),能用但很"土"——依赖 Chrome 装壳,而且没法跨平台。后来换成了 PWA(渐进式 Web 应用),这才是正解:

  • Chrome/Edge/Safari 原生支持"安装为应用"
  • 安装后独立窗口、无地址栏、有 Dock 图标
  • 支持离线访问(Service Worker 缓存)

PWA 四件套

Quartz 没有内置 PWA,我手动加了四样东西(放在 quartz/static/,构建时自动复制到站点根):

quartz/static/
├── manifest.json       # PWA 清单(应用名、图标、主题色)
├── sw.js               # Service Worker(缓存策略)
├── pwa-icon-192.png    # 图标
└── pwa-icon-512.png    # 高清图标

manifest.json 是 PWA 的身份证:

{
  "name": "ReverieVault",
  "short_name": "ReverieVault",
  "display": "standalone",
  "background_color": "#0B192C",
  "theme_color": "#0B192C",
  "icons": [
    { "src": "/static/pwa-icon-192.png", "sizes": "192x192" },
    { "src": "/static/pwa-icon-512.png", "sizes": "512x512" }
  ]
}

Service Worker 负责离线缓存。我的缓存策略: - 页面:网络优先,失败回退缓存(保证内容实时) - 静态资源(CSS/JS/图片):缓存优先 - manifest.json 和 sw.js 本身:永远走网络(这点极其重要,见下文坑)

🔥 PWA 最大的坑:改名字/图标不生效

我在修改 PWA 名称(从中文改成语 ReverieVault)时,重装应用后名字还是旧的,折腾了很久。根因是 Service Worker 的缓存策略把 manifest.json 也缓存了!

Chrome 安装 PWA 时读取的 manifest 会被 SW 拦截,返回的是缓存的旧版本。而 SW 版本不升级时,旧 SW 一直持有旧缓存。

三层修复

  1. manifest.json 永远走网络,不进 SW 缓存:
const isManifest = url.pathname.endsWith('/manifest.json')
const isStatic = !isManifest && /\.(css|js|png|...)$/.test(url.pathname)
  1. SW 版本号升级,activate 时清掉旧缓存:
const CACHE_NAME = 'reverievault-v7'   // 每次改动版本号
// activate 时删除其他版本的缓存
  1. 重新安装 PWAchrome://apps 删除 → 重新安装)

坑 1.5:新增笔记侧边栏不显示(contentIndex.json 缓存)

写知识库的都会遇到:明明新建了笔记,刷新后 explorer 侧边栏里却看不到。折腾到最后发现,根因和 manifest 一模一样——Service Worker 缓存了 /static/contentIndex.json(文件索引),fetch 处理器对它"缓存优先",索引不更新,侧边栏自然不显示新文件。

修复:把 contentIndex.json 也归入"永远走网络"清单:

const isManifest = url.pathname.endsWith('/manifest.json')
  || url.pathname.endsWith('/sw.js')
  || url.pathname.endsWith('/contentIndex.json')   // 新增!
const isStatic = !isManifest && /\.(css|js|png|...)$/.test(url.pathname)

经验总结:凡是"内容索引/配置"类资源(manifest.json、contentIndex.json、sw.js),在 SW 里都必须绕过缓存走网络,否则改了内容不生效。

另一个坑:开发模式的 CSS 缓存

Quartz 开发模式(--serve)默认关闭 CSS 的 hash 命名index.css 文件名不变,改样式后浏览器一直用旧缓存。后来发现根因是代码里 useHashing = !ctx.argv.serve,改成 useHashing = true 后,CSS 文件名带内容 hash,改一次样式浏览器自动拉新文件。

六、最终效果

现在的 ReverieVault:

  • 内容:PARA 组织的项目/领域/资源/归档 + Wiki 提炼层
  • 主题:minimal 极简风 + 站酷小薇标题字体
  • Logo:深蓝底金色 R(品牌色 #0B192C + #D4AF37
  • 形态:本地服务 + PWA 可安装桌面应用
  • 离线可用:SW 缓存,断网也能读笔记

七、给后来者的建议

  1. 内容组织先于工具选型——先想清楚 PARA + Wiki 的结构,再决定用什么工具,Quartz 只是载体
  2. 主题别贪多——15 个主题实测下来,最后用的还是最朴素的 minimal;先选内容为主的主题,再微调字体
  3. PWA 的 manifest 缓存坑——凡是 PWA 配置(名称/图标),记得让 manifest.json 绕过 SW 缓存,否则改了不生效
  4. 让 AI 帮你搭建——整个过程我一行前端代码没写,全是和 Pi 对话完成的:它帮我写配置、调 CSS、修 bug、甚至生成图标。AI 时代,工具链的搭建门槛已经低到"说清楚需求"就够了

本文由 Pi 协助整理,搭建过程的完整技术细节记录在 ReverieVault 的 05-Wiki 知识提炼层。

评论(0)

暂无评论,来抢沙发~


关于本站 · RSS

浙ICP备2025156991号浙公网安备33010802013816号 浙公网安备33010802013816号 © 2026 智能体工场 - [从善如登] All rights reserved.