跳转到内容
关系图谱

vitepress-theme-vault:把 Obsidian 库发布成博客的一站式主题

3,674 字 13 分钟

属性 1
series
VaultKit 包指南

用 Obsidian 写作的人迟早会遇到同一个问题:笔记想发布成博客,但 vault 里的 [[双链]]、callouts、![[图片]] 嵌入这些方言语法,任何通用静态站点生成器都不认识;而且 vault 里混着日记、草稿、模板,绝不能整库上网。@vaultkit/vitepress-theme-vault 就是为这条链路而生的 VitePress 主题——vault 即站点源,白名单发布,Obsidian 语义完整落地,三个文件即可开站。

本文是「VaultKit 包指南」系列的开篇:先讲清主题本体怎么用(安装、全部配置项、发布模型),再给整个 @vaultkit 包家族一个一句话导览。后续文章会逐包深入,比如 callouts 语法指南排版容器指南

为什么需要它

把 Obsidian vault 发布成博客,通常有三条路,各有各的痛:

  • 导出后重写:把笔记复制进 Hexo / Hugo,手工替换双链和 callouts——写作和发布割裂,改一篇同步一篇;
  • Obsidian Publish:官方方案省心,但定制空间有限,也没有评论、RSS、OG 图这些博客设施;
  • 通用 VitePress + 一堆插件:自己攒 wikilink、callouts、slug、发布过滤……每个环节都是坑(pnpm 隔离布局、SSR 水合、死链检查)。

vitepress-theme-vault 走第四条路:站点根即 vault 根srcDir: '.'),主题在构建期完成 Obsidian 方言到 HTML 的全部翻译,发布行为由白名单和 frontmatter 契约控制,写作端零侵入——你在 Obsidian 里怎么写,发布出来就是什么样。

开箱即带的能力

wikilink 双链(别名 / 锚点 / 灰链)、笔记嵌入 transclusion、.canvas 白板、Excalidraw、callouts、行内标签、反向链接、关系图谱、思维导图、RSS、llms.txt、sitemap、逐页 OG 图、Pagefind 中文全文搜索、评论、赞赏、备案页脚……全部内置且逐项可关。

安装

sh
pnpm add -D @vaultkit/vitepress-theme-vault vitepress vue

要求 Node ≥ 20.6,包管理器推荐 pnpm(Tailwind 扫描、图标集、Pagefind 二进制在 pnpm 隔离布局下的坑位已在主题内部消化)。

快速上手:三个文件

ts
// .vitepress/theme/index.ts
export { default } from '@vaultkit/vitepress-theme-vault'
ts
// .vitepress/config.ts
import { createVaultTheme } from '@vaultkit/vitepress-theme-vault/config'
import { defineConfigWithTheme } from 'vitepress'

export default defineConfigWithTheme({
  extends: createVaultTheme({
    site: {
      title: '我的数字花园',
      description: '一座会生长的花园',
      hostname: 'https://example.com',
      author: { name: '园丁', bio: '在这里种想法', avatar: '/avatar.svg' },
      license: { name: 'CC BY-NC-SA 4.0', url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/' },
      giscus: { repo: '', repoId: '', category: '', categoryId: '' },
      beian: { icp: '', police: '' },
      donate: { alipayQr: '', wechatQr: '', paypalUrl: '' },
      friendLinks: [],
    },
  }),
})
jsonc
// package.json
{
  "scripts": {
    "dev": "vitepress dev",
    "build": "vitepress build && vault-theme-postbuild",
    "preview": "vitepress preview"
  }
}

vault-theme-postbuild 是主题自带的构建后处理:关键 CSS 内联 + Pagefind 惰性化,Lighthouse 移动端文章页 90+。目录约定如下:

vault/
├─ Notes/          # 笔记(发布面,slug 化到站点根)
├─ Attachments/    # 附件(![[图片]] 嵌入解析)
├─ pages/          # 功能页(pages/tags.md → /tags)
├─ index.md        # 首页(<BlogHome />)
└─ 其他任意目录     # 一律不发布

site 选项逐组详解

sitecreateVaultTheme() 唯一必填的配置块(类型 VaultSiteIdentity),承载全部站点身份信息。

基本身份

说明
title站点标题(导航栏 / og:site_name / feed 标题)
description站点描述(首页 meta / 无摘要页面的兜底 description)
hostname根部署域名,末尾不带斜杠——sitemap、RSS、og:url 共用这一个值

author:作者卡

说明
name作者名
bio一句话简介(作者卡副标题)
avatar头像,public/ 下的站点绝对路径(如 /avatar.svg
links社交链接数组(作者卡 Follow Me 行;缺省不渲染)

每条社交链接是 { icon, text, url }icongithub(缺省 lucide 集合)或 simple-icons:bilibili 这类 集合:名称 形式,构建期渲染为内联 SVG——名称写错启动即失败,不会拖到线上才发现:

ts
author: {
  name: '园丁',
  bio: '在这里种想法',
  avatar: '/avatar.svg',
  links: [
    { icon: 'github', text: 'GitHub', url: 'https://github.com/xxx' },
    { icon: 'simple-icons:bilibili', text: '哔哩哔哩', url: 'https://space.bilibili.com/xxx' },
    { icon: 'rss', text: 'RSS', url: '/feed.xml' },
  ],
},

giscus 与 comments:评论区

giscus 四个 ID(repo / repoId / category / categoryId齐备评论区才渲染,保持空串即全站关闭评论——不需要额外的开关字段。ID 从 giscus.app 配置页获取,仓库需开启 Discussions 并安装 giscus app。

想换评论系统时用可选的 comments 字段:provider 指定注册名('giscus' 内建),其余键原样透传给 provider 组件:

ts
// .vitepress/theme/index.ts —— 注册自定义 provider
import { registerCommentProvider } from '@vaultkit/vitepress-theme-vault'
import WalineProvider from './WalineProvider.vue' // props: { config, dark, pageKey }

export default {
  extends: VaultTheme,
  enhanceApp: () => registerCommentProvider('waline', WalineProvider),
}
// config.ts → site.comments = { provider: 'waline', serverURL: '…' }

license:文章许可协议

{ name, url },如 { name: 'CC BY-NC-SA 4.0', url: 'https://…' }。文章底部的版权声明卡消费它,展示协议名并链接原文。

beian:备案页脚

说明
icpICP 备案号(空串 = 不显示)
police公安备案号全文(空串 = 不显示)
policeCode公安备案号码(纯数字,用于查询跳转;空则链到备案查询首页)

三项逐项门控,海外部署全部留空即可,页脚不会出现空壳行。

说明
alipayQr支付宝收款码图片(public/ 站点绝对路径;空串 = 渠道关闭)
wechatQr微信收款码图片(空串 = 渠道关闭)
paypalUrlPayPal 收款链接(空串 = 渠道关闭)

三渠道独立门控,全空整卡隐藏

数组,每项 { name, url, description?, avatar? }description 是一句话描述(关于页卡片形态展示、两行截断;侧栏列表形态省略),avatar 缺省时渲染名称首字符的字母圆徽——不用为每个朋友找头像图。

ts
friendLinks: [
  { name: 'VitePress', url: 'https://vitepress.dev', description: '本站的静态站点引擎' },
  { name: 'Obsidian', url: 'https://obsidian.md' },
],

announcement 与 since

  • announcement:公告文本,渲染在首页侧栏公告卡;缺省 / 空串不渲染,\n 保留换行;
  • since:建站日期(YYYY-MM-DD),作者卡据此显示「运行天数」,缺省不显示该格。

顶层选项:lang / dirs / nav / icons

说明缺省
lang站点语言zh-CN
dirs.notes笔记目录(发布到站点根,slug 化 URL)Notes
dirs.pages功能页目录(剥前缀发布:pages/tags.md/tagspages
dirs.attachments附件目录(wikilink 图片嵌入解析)Attachments
nav导航栏 { text, link }[]首页 · 标签 · 归档 · 关于
icons额外图标集(lucide / simple-icons 内置)

icons 值得单说:注册后 Markdown 容器(::: cardicon 属性)与 Vue 组件(~icons/carbon/idea)两路同时可用,数据源是 @iconify-json/<collection>,构建期内联 SVG,零运行时:

ts
import { icons as carbonIcons } from '@iconify-json/carbon'

createVaultTheme({ site, icons: { carbon: carbonIcons } })

features 功能开关

全部开关集中在 features,缺省即合理值,按需逐项覆盖:

说明缺省
searchPagefind 全文搜索(中文分词优化);对象形态覆写文案 { btnPlaceholder, placeholder, emptyText, heading }true
feedRSS feed.xml + JSON Feedtrue
llmsllms.txt / llms-full.txt(面向 LLM 的站点摘要)true
robotsrobots.txt(Sitemap 指向)true
embedsDeferSrc嵌入类 iframe(bilibili / codepen / stackblitz / web-frame)进视口才注入 src,保 bfcachetrue
linkPreview站内链接悬停 iframe 预览(Nolebase)true
readingProgress页面阅读进度条true
scrollNavigator悬浮滚动导航按钮(回顶部 / 到底部)true
motionGSAP 入场 / 切页动画(prefers-reduced-motion 始终尊重)true
ogImage构建期逐页 OG 分享图(satori + resvg,笔记页专图,非笔记页回退 /og.pngtrue
aliasRedirectsfrontmatter aliases → 构建期重定向 stub 页(meta refresh + canonical + noindex)true
devNotesRestartdev 下监听笔记目录增删改名,自动重载配置true
pagination文章列表分页(首页 / 标签页,?page=N 深链);{ perPage } 覆写每页篇数{ perPage: 10 }
analytics站点统计:{ provider: 'umami', src, websiteId }{ provider: 'plausible', domain };DNT 与 localhost 自动豁免关闭
notFoundSuggest404 页「你可能在找」(slug 分词 → Pagefind 检索,dev 降级站内模糊匹配)true
pwaPWA / 离线:true 用站点身份推导 manifest,对象深度覆写false

markdown 管线开关

markdown 块控制 Markdown 管线的每一个环节,同样逐项可关:

说明缺省
lineNumbers代码块行号true
codeThemeshiki 主题 { light, dark }github-light / github-dark
calloutsObsidian callouts(13 类 + 别名 + 折叠,详见本系列下一篇)true
mathLaTeX 数学公式(markdown-it-mathjax3 构建期渲染为内联 SVG,客户端零依赖)false
transclusion笔记嵌入 ![[笔记]] / ![[笔记#标题]] / ![[笔记#^块]](循环检测,嵌套上限 3 层)true
inlineTags正文行内标签(渲染徽章 + 计入标签页;代码 / 链接内豁免)true
canvas![[白板.canvas]] JSON Canvas 嵌入(构建期渲染静态画布)true
excalidraw![[画稿.excalidraw]] 嵌入(sidecar SVG / PNG 导出图,暗色自适应)true
mermaidmermaid 围栏 → 客户端渲染true
obsidianSyntax任务清单 / ==高亮== / 脚注true
typographyNuxt UI Typography 容器(card / steps / code-collapse…,详见本系列第三篇)true
fileEmbeds::: github-file / ::: cnb-file 远程文件嵌入true
repoCard::: repo-card 仓库卡片true
npmCard::: npm-card npm 包卡片true
embeds::: bilibili / ::: codepen / ::: stackblitz / ::: web-frametrue
readingTime阅读时间统计(中英分轨字数 → frontmatter.readingTimetrue
groupIcons代码组图标(vitepress-plugin-group-icons)true

主题内部已把 gfmAlerts: falsecleanUrls、图片懒加载、SSR noExternal 这些配套细节处理好,消费方无需操心。

发布模型:默认隐私 + 定时发布

这是主题与通用博客框架差异最大的一块,围绕「vault 里不是所有东西都该上网」设计:

  • 白名单目录:只有 Notes/pages/index.md 进构建,vault 里其他一切目录(日记、模板、剪藏)默认排除——隐私是缺省态,不是需要记得配置的选项;
  • 单篇豁免:frontmatter 写 publish: false 即把某篇笔记从发布面摘除;
  • 定时发布:日期在未来的笔记 dev 可预览、build 自动排除。配合 CI 每日构建,到点即自动上线,不需要任何服务端;
  • fail-fast:笔记 slug 化后如果与保留路径(feed.xml 等)或其他笔记冲突,构建启动即报错,而非静默覆盖。
笔记契约是零侵入的

文件名即标题(2024-01-01 我的想法.md → 标题「我的想法」+ 日期);日期字段按 datecreatedpublishedstart 链取值;摘要从正文首段自动提取,喂给 description / RSS / 卡片 / OG 图。你不需要为发布往 frontmatter 里塞任何字段。

写作 DX

  • dev 免重启:新增 / 删除 / 改名笔记、翻转 publish 开关,dev server 自动重载配置(唯一例外:新增顶层目录仍需手动重启);
  • 改名防死链:frontmatter aliases 为旧标题生成重定向页;
  • 系列连载:frontmatter 写 series: 系列名 即入列,文中自动渲染系列导航卡(第 N/M 篇 + 全篇目 + 上下篇),pages/series.md<SeriesPage /> 得到归档页——本文的导航卡就是这么来的;
  • 置顶与上下篇pinned: true 首页置顶;上 / 下篇按日期序自动注入,无需手写。

包家族总览

主题的能力由 @vaultkit 系列独立包组装而成,全部可脱离主题单独使用。一句话导览:

Markdown / 内容管线

  • markdown-it-obsidian-callouts——Obsidian callouts 语法(13 类 + 14 别名 + 折叠)
  • vitepress-plugin-nuxt-typography——card / callout / steps / code-collapse 排版容器
  • vitepress-plugin-obsidian-canvas——.canvas 白板静态渲染
  • vitepress-plugin-reading-time——中英分轨字数统计与阅读时长

嵌入 / 远程内容

  • vitepress-plugin-bilibili——B 站视频嵌入
  • vitepress-plugin-web-frame——浏览器窗口样式 iframe
  • vitepress-plugin-code-playground——CodePen / StackBlitz 嵌入
  • vitepress-plugin-repo-card——GitHub / CNB 仓库卡片
  • vitepress-plugin-npm-card——npm 包信息卡片
  • vitepress-plugin-remote-file——远程源码文件嵌入
  • repo-platform-kit——仓库平台 API 统一取数层(上面两位的底座)

站点设施(构建期)

  • vitepress-plugin-feed——RSS + JSON Feed
  • vitepress-plugin-llms——llms.txt / llms-full.txt
  • vitepress-plugin-robots——robots.txt
  • vitepress-plugin-og-image——逐页 OG 分享图(satori)
  • vitepress-plugin-umami / vitepress-plugin-plausible——隐私优先统计注入

UI 组件

  • vitepress-plugin-local-graph——Obsidian 风格关系图谱
  • vitepress-plugin-mindmap——标题思维导图
  • vitepress-plugin-content-toc——circuit 走线目录
  • vitepress-plugin-contribution-graph——创作热力图
  • vitepress-plugin-word-cloud——标签词云
  • vitepress-plugin-image-preview——图片灯箱预览
  • vitepress-plugin-reading-progress——阅读进度条
  • vitepress-plugin-scroll-navigator——回顶部 / 到底部浮钮
  • vitepress-plugin-giscus——giscus 评论区
  • vitepress-plugin-copyright——版权声明卡
  • vitepress-plugin-donate——赞赏卡

本系列接下来会逐包展开。下两篇已经就位:markdown-it-obsidian-callouts:Obsidian Callouts 语法完全指南 拆解 callouts 的全部语法形态,nuxt-typography:card、callout、steps 排版容器完全指南 覆盖五种排版容器的每一个属性。

常见问题

评论区为什么不显示?

site.giscus 四个 ID 必须齐备(repo / repoId / category / categoryId),缺一即全站关闭。检查仓库是否开启 Discussions、是否安装 giscus app。

未来日期的笔记为什么线上看不到?

这是定时发布的设计行为:dev 可预览、build 排除。给 CI 配一条每日定时构建,到点自动上线。

社交链接图标写错会怎样?

构建启动即抛错并指出缺失的图标名——所有图标(作者卡、容器、callouts)都在构建期渲染为内联 SVG,错误不会漏到线上。

能只用主题的一部分能力吗?

可以,两条路:features.* / markdown.* 逐项关闭;或者跳过主题,单独安装对应的 @vaultkit 插件包。

相关链接

系列篇目

本文是「VaultKit 包指南」系列的总览开篇,后续 28 篇按主题分组逐包展开:

Markdown 语法与排版

可视化组件

阅读体验与文章组件

嵌入容器与取数内核

站点设施

  • feed —— 给博客配上 RSS 与 JSON Feed
  • llms —— 让站点对 AI 友好的 llms.txt
  • robots —— 一分钟配好 robots.txt
  • og-image —— 无浏览器管线的逐页 OG 分享图
  • umami —— 隐私优先的 Umami 统计接入
  • plausible —— 隐私优先的 Plausible 统计接入