2026/10/22

个人博客2.0:架构、功能与 UI 设计沉淀

知识库

个人博客2.0:架构、功能与 UI 设计沉淀

BlogX_x「树码空间」——AI 驱动的个人数字花园。本文以当前线上形态为准,沉淀它的设计架构、功能全景与 UI 设计决策。 2026-10-22 全面重写,对齐「内容出仓」后的真实架构;旧稿中已失效的表述(写死的模型供应商、本地目录同步流程等)一并修正。

一、定位与设计哲学

1.1 双重角色

BlogX_x 不只是一个博客,它同时扮演两个角色:

  • 个人博客:策展外链技术长文(自动抓取 + 中英翻译),沉淀自己的工程实践
  • 知识库载体:按条目导入 Obsidian 笔记,构建可检索、可关联、可被 AI 读取的知识网络

两者共享同一套语义搜索与知识图谱底座——每一篇内容都被向量化、被关联、被可视化。

1.2 三条设计原则

  1. Content-first:内容优先,轻交互、低维护。宁可少一个功能,不多一处需要照看的后台。
  2. AI 是检索与回答层,不是内容真源:Markdown 归人所有,AI 只负责理解、检索、翻译与回答;AI 不生成内容真源,也不决定内容形态。
  3. 本地脚本 + 内容集合优先于自建后端:不引入额外后端服务,管理面收敛为一套轻量面板 + 一组可脚本化的 CLI。

1.3 工程三支柱

  • VibeCoding——注重用户体验与交互感受,让界面有自己的气质;
  • SpecCoding——严格的数据结构定义与类型约束,schema 单一定义处,双端(Astro / Node)共用;
  • Harness Design——完整的工具链与自动化流程,把重复劳动交给脚本与流水线。

二、总体架构

2.1 分层图

┌──────────────────────────────────────────────────────┐
│                      用户浏览器                        │
│   文章 · 知识库 · Wiki · 图谱 · AI 搜索 · 服务器 3D     │
├──────────────────────────────────────────────────────┤
│            Astro 6 (SSR) + React 19 islands           │
│        Tailwind 4 token 体系 · Vercel 部署             │
├──────────────────────────────────────────────────────┤
│   API 层:ai-search / knowledge-graph / search / …     │
│   管理面:/admin 面板(生产由 middleware 拦截)          │
├───────────────────────┬──────────────────────────────┤
│  LanceDB content 表    │  LanceDB blog_index 向量表    │
│  (内容唯一真源)       │  (搜索/图谱派生索引)         │
├───────────────────────┴──────────────────────────────┤
│   Upstash Redis/KV:留言 · 想法 · 限流 · 健康检查       │
├──────────────────────────────────────────────────────┤
│  外部服务:OpenAI 兼容 LLM(LLM_* 统一配置出口)        │
│  · 嵌入服务(向量编码)· Obsidian vault(可选输入源)    │
│  · MCP server(stdio / HTTP,供 Agent 读知识库)        │
└──────────────────────────────────────────────────────┘

2.2 内容真源:一张 content 表

架构上最关键的一条决策:内容不在 git 里。

层是什么谁写
LanceDB content 表内容唯一真源。字段:collection / path / frontmatter / body / originalBody / translatedBody / status / updatedAt管理面板、content:intake、content:publish、sync-obsidian-kb
src/content/**构建产物。predev / prebuild 由 content-pull 按原嵌套路径写盘,.gitignore 忽略只有 content-pull

带来的直接收益:

  • 克隆即建:新机器只需 .env + npm install,构建时自动拉全量内容;
  • 草稿跨机器可见:status: draft 只存在于表里、不写盘,天然不进构建产物;
  • 内容与代码解耦:内容变更不触发重建,发布时主动打 Deploy Hook,节奏由人控制。

2.3 运行时形态

层技术说明
框架Astro 6(output: "server")SSR,经 @astrojs/vercel 部署
交互React 19 islands只给需要交互的模块(图谱、留言、阅读栏、3D 机箱…)
样式Tailwind 4 + global.css 设计 token见第五节
向量库LanceDB(本地 .lancedb + 云端)双表:content(内容)+ blog_index(向量)
LLM任一 OpenAI 兼容服务配置统一走 LLM_API_KEY / LLM_BASE_URL / LLM_MODEL 出口,不绑定供应商
KVUpstash Redis(@vercel/kv)留言、想法、限流
协议MCP(stdio / HTTP)AI 助手直读知识库

三、内容模型与管线

3.1 六个集合

集合内容路由
posts策展外链文章(双语)/posts
knowledgeBase知识库笔记(嵌套分类路径)/knowledge-base
wiki站点 Wiki(sources/concepts 编译层)/wiki
repos / skills / projects仓库 / 技能包 / 项目展示/repos /skills …
toolbox策展外部工具/toolbox

Schema 的唯一定义处在 src/lib/content-schemas.ts,Astro 与 Node 脚本双端加载同一份;面板写入走 passthrough 校验,保留 schema 之外的脚本字段(如 posts 的抓取元数据),静默丢弃即丢数据。

3.2 posts:外链策展 + 双语翻译

「文章」的形态是外链收藏 + 自动化加工,不是自己写长文:

  1. 收录只需一条 sourceUrl(title / description / 作者 / 语言均可自动提取);
  2. 构建期 fetch-articles 抓取正文、调用 LLM 全文翻译,原文与译文存进 content 表的 originalBody / translatedBody;
  3. 详情页原文/译文一键切换(纯前端,零延迟),保留原作者归属与来源回链;
  4. 只补缺:语料完整的记录构建期空转,不打 LLM 不写库;失败不静默——抓取失败原记录一个字节不动,翻译失败保留旧译文并逐条报告。

3.3 knowledge-base:嵌套分类 + 按条目导入

  • 路径即分类(如 辊刀软件/路径编辑功能V2.0),列表页按第一层目录分组,目录名就是站点分类名;
  • Obsidian vault 是可选输入源:sync-obsidian-kb 按条目点名导入,禁止整库自动同步——vault 里有私人笔记,整库同步等于把它们推上公网站点;
  • 排除清单里的条目即使被点名也拒绝导入;导入幂等(按 path 先删后插),且绝不把在架条目撤下。

3.4 wiki:sources / concepts 双层编译

站点 Wiki 是从知识库编译出来的衍生层:

  • sources/——每篇知识库笔记一篇「来源摘要」(关键结论 + 可复用方法),body 里标注原文路径;
  • concepts/——跨来源的概念沉淀,用 [[双链]] 织网;
  • index / log——入口清单与操作日志。

知识库是原料,Wiki 是蒸馏物;改知识库要同步摘要层,否则衍生层失真。

3.5 发布链路

输入(URL / 文件 / 粘贴正文 / Obsidian 笔记)
   → content:intake(抓取 + LLM 提取 + 校验 → content 表草稿)
   → content:publish(校验发布 → status: published → 打 Vercel Deploy Hook)
   → 构建期 content-pull 写盘 → init-db 增量向量化 → 站点更新

管理面板与 CLI 共用同一份 intake 实现;发布门禁一致:intake 自述失败的草稿默认拒绝发布,显式覆盖才放行。

3.6 向量索引

blog_index 是派生索引,不是真源:init-db 对内容做嵌入(1024 维),增量更新(hash 对比:新增/修改/删除三分),内容删了索引也会跟着删。搜索与图谱都读它;检索质量有问题时重建索引,而不是在 UI 里硬编码结果。

四、功能全景

4.1 AI 对话式搜索

首页主入口。自然语言提问 → 向量检索 → 相关内容卡片 + LLM 生成的回答,支持连续对话上下文。工程细节:

  • 双 scope:站内内容(site)与工具箱(toolbox)分开检索;
  • 限流:每 IP 滑动窗口(默认 60 秒 5 次);
  • 交互上有停止/清除对话控制(博客式按钮,可中断生成中的回答);
  • 结果区加宽卡片布局,hover 时同级卡片自动变暗聚焦。

4.2 知识图谱

基于向量相似度自动建边——每个节点取最近邻连成关系网络,力导向图渲染(react-force-graph-2d + d3-force)。节点上限、每节点边数、相似度阈值都可调。交互:滚轮缩放、点击节点跳转原文。仅桌面端展示,移动端隐藏——小屏读图不如读列表。

4.3 阅读体验:Reading Rail

文章 / 知识库 / Wiki 详情页统一挂左侧阅读栏(交互对标 claude.dev/blog 的 rail):

  • 自动解析正文 h2–h4 生成章节树,当前章节高亮,点击跳转;
  • ▓░ 字符风格阅读进度条,顶栏另有细线进度随滚动生长;
  • 双模式:article(线性阅读,当前组展开)/ reference(查阅跳转,子树常开);
  • 正文替换(如原文⇄译文切换)后自动重建章节树。

4.4 服务器页:3D 机箱

首页像素标题「树码空间」之外,站点有一台线条画风的可交互 3D 机箱(/server):从水冷到电源逐件拆看,部件引出标注,把「这台数字花园的机器」具象化——它同时是隐喻导览:CPU 对应 AI 搜索与翻译管线,冷排对应向量索引,等等。

4.5 互动与后台

  • 关于页:留言(FunMessages)+ 想法箱(IdeaBox),轻交互,写入 KV,限流 + 净化;
  • 管理面 /admin:posts / knowledge-base / wiki / repos / skills / projects / toolbox / messages / ideas 全集合 CRUD,posts 另有 AI 上传面板;生产环境整面 404,写入面在公网为零;
  • MCP:stdio / HTTP 双形态 MCP server,让 AI 助手直接读知识库与 Wiki——博客不只是给人看的,也是给 Agent 用的记忆库。

五、UI 设计

5.1 视觉基调:暖纸 + 牛血红

设计方向是暖纸工业插画(warm paper + industrial illustration),浅色单主题:

  • 纸面底色 #efe5cf,棕墨线条,牛血红 #b93b28 是全站唯一强调色;
  • 内容与插画在同一张连续的「纸」上,没有悬浮玻璃、没有弥散光晕;
  • 小圆角(2–5px,像裁切的纸边),卡片阴影是短偏移实边(1px 2px 0),不是柔和投影;
  • 选区、进度条、hover 态全部收敛在牛血红一族。

5.2 设计 token

全部集中在 src/styles/global.css 的 CSS 变量:色板(bg / surface / text / line / accent 系列)、圆角、阴影、缓动(expo-out 三档时长)、字体四件套:

用途字体
正文Geist + Noto Sans SC
章节标题Noto Serif SC(书卷气)
技术标签 / 代码Geist Mono
展示标题Manrope

改气质只动 token,不动组件。

5.3 关键界面决策

决策理由
首页像素标题(PixelWaveTitle「树码空间」)品牌记忆点,像素波是站点的视觉签名
AI 搜索置于 hero 中央搜索是第一入口,不是附属功能
阅读栏章节树 + 字符进度条长文阅读要有空间感;▓░ 是编辑器气质的克制表达
知识库列表「主区 + 右侧分类目录」双栏分类即路径,目录即导航
hover 聚焦(同级卡片变暗)信息密度高时帮视线锁定目标
文章预览纸感滚动条细节处延续「纸」隐喻
图谱桌面限定移动端宁缺毋滥
light-only,不做暗色主题纸的隐喻经不起反色,主题分裂成本高于收益

5.4 响应式与可访问性

  • 375px 手机到 2560px 4K 全档自适应,正文无横向溢出;
  • 切换按钮、搜索框等交互控件带 aria-label,键盘可达;
  • 知识库移动端改横向分类标签条,导航折叠抽屉;
  • 动效克制:入场 stagger、hover 微移,全部走统一的 expo-out 缓动。

六、经验与取舍

  1. 内容出仓(移出 git)是分水岭:此前一篇私人笔记被同步进仓库、引用不存在的图片,直接把构建打挂。内容进 LanceDB 后,构建产物可清空重建,脏数据不再污染仓库,也让「内容变更 ≠ 代码变更」成为可能。
  2. 失败要响亮,不要静默降级:拉不到内容且磁盘为空时构建直接失败——空站点比失败更难发现;写库路径在凭据缺失时拒绝写入,而不是「表面成功写错靶」。
  3. 只补缺,不重翻:翻译管线的增量策略省下大量 LLM 调用;「本来就缺」与「被改坏」用同一个谓词区分,回归才报警。
  4. 私人与公开的边界要硬:按条目导入 + 排除清单 + 生产环境管理面 404,三道闸都指向同一条线——写入面在公网为零。
  5. 配置出口收敛:外部 LLM 按任一 OpenAI 兼容服务表述,统一走 LLM_* 配置出口;供应商是可替换的实现细节,不是架构陈述。
  6. 衍生层要标源:Wiki 摘要标注原文路径,知识库移动/删除时同步更新——引用悬空的摘要比没有摘要更误导。

本文是 BlogX_x 当前形态的架构快照。工程细节以仓库内文档与源码为准。