← All blog posts
Jun 19, 2026·5 min readBlogCodingProductObsidianWorkflow

从 Lovable 原型到真实博客:一个本地 Publisher + Obsidian 部署工作流的诞生

From Lovable Prototype to Real Blog

详细记录如何把一个 AI 生成的 Lovable 原型,改造成一个可长期维护的 TanStack Start 博客。亮点是自建的本地 Publisher Dashboard + Obsidian 写作发布系统。

这个博客的第一行代码不是手写的,是 Lovable 生成的。

2026 年 6 月 18 日,我在 Lovable 里描述了一个安静的、暖白色调的、带卡片阵列的博客,AI 给了我一个完整的原型:首页有滚动横幅、文章卡片排列整齐、About 页面安静地点着头像和简介。那一刻的感觉是"对了"——视觉语言对了。

Pasted image 20260622132307.png

但原型和能长期维护的工程之间,有一条需要亲自走过的线。这篇文章记录这条线上每一段路,重点讲我自认为做得最漂亮的部分:本地 Publisher Dashboard + Obsidian 写作发布机制

一、原型之后的第一步:工程化

Lovable 给的原型有这些好东西:

  • TanStack Start 作为框架(文件路由,SSR,TypeScript 原生)
  • Tailwind CSS v4 + shadcn/ui 风格的组件
  • 完整的首页、Blog 列表、文章详情、Projects、About 页面

但也有这些问题:

  • 混用了两种包管理器,依赖装到一半就挂了
  • 组件全堆在一个扁平的大目录里,没有任何分层
  • 文章数据是硬编码在代码里的,改一行就要动代码

第一天晚上我做了三件事:

  1. 统一工具链:清理掉多余的包管理器配置,全部走单一工具链。顺手补了类型检查和代码格式化脚本。工程化的第一天原则:构建必须能跑,类型必须能过。
  1. 组件分层:把堆在一起的文件按功能拆开——布局组件放一起,首页专用组件放一起,博客相关的放一起,项目展示的放一起。一眼就能看出每个文件该去哪找。
  1. 内容文件化:把硬编码的文章数据拆成独立的 Markdown 文件,用框架的文件导入能力动态加载。这一步是关键转折——文章变成了文件,文件就可以被任何编辑器管理,编辑器管理就可以做自动化发布。

经过这一轮,项目从"能看"变成了"能改"。

二、核心亮点:Obsidian → Publisher → Git → Vercel

这是整个博客最让我得意的地方。

2.1 为什么要自己做 Publisher?

我的写作环境是 Obsidian。文章写在 Obsidian 里,有元数据、有 ![[图片]] 引用、有 [[笔记链接]] 连接到其他笔记。如果每次发文章都要手动复制 Markdown、手动找图片、手动改链接、手动 commit,这个过程会消磨掉所有写作的成就感。

市面上当然有成熟的方案——Notion + API、Headless CMS、甚至直接把 Obsidian 仓库发布。但我不想引入外部服务,也不想把我的本地笔记文件夹整个暴露到公网。

我想要的是:打开一个本地网页,勾选想发的文章,点一个按钮,就发布到线上。

所以我自己做了一个。

2.2 Publisher Dashboard 能做什么

一条命令启动后,浏览器打开一个本地地址,你会看到一个中文界面:

Pasted image 20260622132238.png

左侧是文章列表,每篇文章显示文件名、标题、日期、标签和状态:

  • 🟢 新文章 — Obsidian 里有,博客里还没有
  • 🟡 有改动 — Obsidian 里改了,博客里的旧版本需要更新
  • 已发布 — 两边一致,没有新变化
  • 🔴 草稿/有问题 — 草稿或格式不对,不会发布

右侧是操作面板,可以:

  • 检查选中文章 — 验证元数据是否完整、图片能不能找到、链接合不合法
  • 模拟发布 — 预览转换后的 Markdown,但不动任何真实文件
  • 正式发布 — 把文章转换成博客格式、图片自动复制到正确的目录、所有 Obsidian 特殊语法转成标准 Markdown
  • 发布并推送 — 发布完直接 commit 并 push 到 GitHub。GitHub 推了,部署平台就自动上线。

右上角还有一个访问令牌输入框,所有写操作都要输入正确的令牌才能执行。这个令牌存在本地配置文件里,不会被提交到代码仓库。

2.3 Obsidian → Markdown 的转换细节

这一步是最多坑的。Publisher 的核心转换逻辑做了这些事:

  1. 笔记链接转换[[某篇笔记的标题]] 自动变成博客内部文章链接。如果链接指向的笔记还没发布,就转成纯文本显示,不让死链接进入发布内容。
  1. 图片处理![[粘贴的图片.png]] 自动找到原始图片文件,复制到博客的图片目录下,并重写成标准 Markdown 图片语法。这一步要处理很多边界情况——中文文件名、空格、图片来自哪个文件夹。
  1. 外链和代码块保护:外部链接原样保留。代码块里的内容不做任何处理,防止把代码注释或示例里的方括号误当成链接来转换。
  1. 文件名规范化:Obsidian 里可以用中文命名笔记,发布时会自动转成英文或拼音的 URL 友好格式。空格、下划线、特殊字符都能正确处理。
  1. 安全底线:本地文件路径不会出现在发布后的内容里。构建失败时不会 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 文件动态加载文件化管理,任何编辑器都能写
部署Vercelpush 代码 → 自动部署
DNSCloudflare域名代理 + SSL
发布自建 Publisher Dashboard本地操作、一键发布、自动 commit
写作Obsidian本地 Markdown、笔记链接、图片粘贴

*写于 2026 年 6 月 19 日