从 Lovable 原型到真实博客:一个本地 Publisher + Obsidian 部署工作流的诞生
From Lovable Prototype to Real Blog
详细记录如何把一个 AI 生成的 Lovable 原型,改造成一个可长期维护的 TanStack Start 博客。亮点是自建的本地 Publisher Dashboard + Obsidian 写作发布系统。
这个博客的第一行代码不是手写的,是 Lovable 生成的。
2026 年 6 月 18 日,我在 Lovable 里描述了一个安静的、暖白色调的、带卡片阵列的博客,AI 给了我一个完整的原型:首页有滚动横幅、文章卡片排列整齐、About 页面安静地点着头像和简介。那一刻的感觉是"对了"——视觉语言对了。

但原型和能长期维护的工程之间,有一条需要亲自走过的线。这篇文章记录这条线上每一段路,重点讲我自认为做得最漂亮的部分:本地 Publisher Dashboard + Obsidian 写作发布机制。
一、原型之后的第一步:工程化
Lovable 给的原型有这些好东西:
- TanStack Start 作为框架(文件路由,SSR,TypeScript 原生)
- Tailwind CSS v4 + shadcn/ui 风格的组件
- 完整的首页、Blog 列表、文章详情、Projects、About 页面
但也有这些问题:
- 混用了两种包管理器,依赖装到一半就挂了
- 组件全堆在一个扁平的大目录里,没有任何分层
- 文章数据是硬编码在代码里的,改一行就要动代码
第一天晚上我做了三件事:
- 统一工具链:清理掉多余的包管理器配置,全部走单一工具链。顺手补了类型检查和代码格式化脚本。工程化的第一天原则:构建必须能跑,类型必须能过。
- 组件分层:把堆在一起的文件按功能拆开——布局组件放一起,首页专用组件放一起,博客相关的放一起,项目展示的放一起。一眼就能看出每个文件该去哪找。
- 内容文件化:把硬编码的文章数据拆成独立的 Markdown 文件,用框架的文件导入能力动态加载。这一步是关键转折——文章变成了文件,文件就可以被任何编辑器管理,编辑器管理就可以做自动化发布。
经过这一轮,项目从"能看"变成了"能改"。
二、核心亮点:Obsidian → Publisher → Git → Vercel
这是整个博客最让我得意的地方。
2.1 为什么要自己做 Publisher?
我的写作环境是 Obsidian。文章写在 Obsidian 里,有元数据、有 ![[图片]] 引用、有 [[笔记链接]] 连接到其他笔记。如果每次发文章都要手动复制 Markdown、手动找图片、手动改链接、手动 commit,这个过程会消磨掉所有写作的成就感。
市面上当然有成熟的方案——Notion + API、Headless CMS、甚至直接把 Obsidian 仓库发布。但我不想引入外部服务,也不想把我的本地笔记文件夹整个暴露到公网。
我想要的是:打开一个本地网页,勾选想发的文章,点一个按钮,就发布到线上。
所以我自己做了一个。
2.2 Publisher Dashboard 能做什么
一条命令启动后,浏览器打开一个本地地址,你会看到一个中文界面:

左侧是文章列表,每篇文章显示文件名、标题、日期、标签和状态:
- 🟢 新文章 — Obsidian 里有,博客里还没有
- 🟡 有改动 — Obsidian 里改了,博客里的旧版本需要更新
- ⚪ 已发布 — 两边一致,没有新变化
- 🔴 草稿/有问题 — 草稿或格式不对,不会发布
右侧是操作面板,可以:
- 检查选中文章 — 验证元数据是否完整、图片能不能找到、链接合不合法
- 模拟发布 — 预览转换后的 Markdown,但不动任何真实文件
- 正式发布 — 把文章转换成博客格式、图片自动复制到正确的目录、所有 Obsidian 特殊语法转成标准 Markdown
- 发布并推送 — 发布完直接 commit 并 push 到 GitHub。GitHub 推了,部署平台就自动上线。
右上角还有一个访问令牌输入框,所有写操作都要输入正确的令牌才能执行。这个令牌存在本地配置文件里,不会被提交到代码仓库。
2.3 Obsidian → Markdown 的转换细节
这一步是最多坑的。Publisher 的核心转换逻辑做了这些事:
- 笔记链接转换:
[[某篇笔记的标题]]自动变成博客内部文章链接。如果链接指向的笔记还没发布,就转成纯文本显示,不让死链接进入发布内容。
- 图片处理:
![[粘贴的图片.png]]自动找到原始图片文件,复制到博客的图片目录下,并重写成标准 Markdown 图片语法。这一步要处理很多边界情况——中文文件名、空格、图片来自哪个文件夹。
- 外链和代码块保护:外部链接原样保留。代码块里的内容不做任何处理,防止把代码注释或示例里的方括号误当成链接来转换。
- 文件名规范化:Obsidian 里可以用中文命名笔记,发布时会自动转成英文或拼音的 URL 友好格式。空格、下划线、特殊字符都能正确处理。
- 安全底线:本地文件路径不会出现在发布后的内容里。构建失败时不会 commit,不会 push。Git 操作只提交本次生成的文件,从不用全量添加。
2.4 撤稿也一样简单
如果发出去的文章想撤回,Dashboard 上有两个选择:
- 软撤稿:给文章打上"草稿"和"已撤回"标记。文章还在仓库里,但博客上看不到了。
- 硬撤稿:删除博客里的文章文件和图片目录。但不会删 Obsidian 里的原始笔记——你写的每一个字都永远安全。
两种方式都不会强制推送,不会重写 Git 历史。就是一次普通的 commit。
2.5 为什么这套流程好
写文章最好的状态是什么都不用想。打开 Obsidian,打字,存盘。然后在 Publisher 里点一下发布——图片自动跟过去,链接自动转好,commit message 自动记录清楚是哪篇文章更新了。
整个过程不需要:
- 手动复制粘贴 Markdown
- 手动找图片路径
- 手动改笔记链接
- 记 git 命令
- 登录任何管理后台
只有一个本地网页,一个按钮,一个令牌。
三、其他值得一提的设计
3.1 SEO 和 Open Graph
每篇文章自动生成搜索引擎需要的元数据和社交分享卡片(标题、描述、封面图、发布时间、标签)。站点地图和爬虫规则文件在每次构建时自动生成。草稿和已撤回的文章不会出现在站点地图里。
3.2 Markdown 渲染
支持各级标题、有序和无序列表、引用块、行内代码、代码块、表格、任务列表。图片可以点击放大预览,支持滚轮缩放和拖拽平移。所有元素在最小屏幕手机上测试过——代码块内部横向滚动,表格不撑破页面,图片自适应宽度。
3.3 中英双语
博客面向中英文读者,每个关键位置都做了双语支持:页面描述英文在上中文在下,文章标题可以同时有中英文两行,标签中英文混用,搜索支持两种语言。
3.4 专题系列页
博客有一个动态的系列入口页面。文章只要在元数据里标记自己属于哪个系列,就会自动归入对应页面。有文章就显示专题卡片,没文章就自动消失——不需要手动维护列表。
四、技术栈一览
| 层 | 选型 | 为什么 |
|---|---|---|
| 框架 | TanStack Start + React + TypeScript | 文件路由、服务端渲染、类型安全,原型自带 |
| 样式 | Tailwind CSS + shadcn/ui | 保留原型的视觉语言 |
| 内容 | Markdown 文件动态加载 | 文件化管理,任何编辑器都能写 |
| 部署 | Vercel | push 代码 → 自动部署 |
| DNS | Cloudflare | 域名代理 + SSL |
| 发布 | 自建 Publisher Dashboard | 本地操作、一键发布、自动 commit |
| 写作 | Obsidian | 本地 Markdown、笔记链接、图片粘贴 |
*写于 2026 年 6 月 19 日