2026年年中,为个人应用来点 Vibe Coding

HN Build in Public AI 2026-08-14T07:18:20.884323

有几个手机应用我已经想要好一阵子了,而且说实话,它们基本是只为我一个人做的。

Toucan Music 显示专辑封面

所以过去这一个月左右,我凭着感觉(vibe coding)写出了 Toucan(选“仅本地”模式就能直接试用,你输入的数据都会留在浏览器里)。不管怎么说,源码在这里。不过说实话,我还没自信到敢说这是一个“正式发布”——具体原因下文再讲。

架构

上面提到的这些应用需要在手机上跑,还得把数据同步到网页端,这样桌面也能用。常规做法是给自己搭一个私人软件即服务(SaaS):配一台自己的服务器和数据库,然后再做一个手机应用。

这感觉有点用力过猛——笨重、臃肿,而且扩展性也不行。我一直很欣赏如今所谓的“本地优先”(local-first)软件运动。它的核心想法是:数据主要存储在各台设备本地,通过一个标准化的同步服务器在设备之间传递数据。这样操作会非常快,因为一切都只在本地进行;同步则在后台默默完成。你可以把它想成类似 Dropbox 的东西,只不过同步的是数据库里的数据。

其中有些数据相当私密——尤其是人脸,但哪怕是餐馆推荐里的姓名也很敏感。所以我倾向于把数据同步到自己的一台服务器上,那台服务器托管在一家很不错的本地 ISP(互联网服务提供商)那里。

结果挺失望的——居然没有标准的个人数据同步服务器软件。我本来期待至少有个像Nextcloud那样有一定人气的东西。你可能没听说过Nextcloud,它是一个自托管的文件同步服务器(以及更多功能)。

最后我和Fable选了Yjs,这是目前最流行的本地优先协议。我想要的只是一个能写入SQLite数据库的简单服务器(这样托管和备份都省心)。Fable找到了小众的Hocuspocus,简单且够用(不过事后发现它在数据库文件里的格式不透明,是二进制,但那是另一个故事了)。

我也花了一阵子琢磨能不能用Rust写界面,但最后还是图省事,用Javascript做了个渐进式网页应用(PWA)。装到我的安卓手机上之后(通过Chrome安装,不知为何Firefox不行),用起来跟原生应用没差别。网页版和手机版是同一套代码,行为一致。即便有LLM编程智能体帮忙,这也能省去大量麻烦。

基本流程

在咖啡店使用Toucan Places

大部分工作是在每月18英镑的Claude套餐上完成的,主要用Opus。Fable在前期规划上帮了不少忙,但我不确定它起了多大作用——有几个决定反正后来证明是错的,被重构掉了。

我的流程放到现在的LLM编程阶段算是很常规的:有个plans/目录,任何大改动先在那里做设计。我来编辑、拍板,然后清空上下文窗口,让智能体照着计划实现。

如果是重要的界面或设计改动,我会让Claude生成一个包含几种方案的设计制品。质量出乎意料地高,尤其是迭代几轮之后。

Bug和任务我则用一个简单的to-do文件管理。智能体完成后会逐项勾掉,然后我来验收并删除。

这些任务大多归在“Polish”(打磨)这个标题下。因为我要给出大量产品和用户体验方面的细致反馈。我在日常使用这些应用时会随手记下来。每个应用都有几十上百条。这也是我认为这事目前很难大规模推广给普通人的一个重要原因——详见下文。

我固执地没有升级到更贵的AI编程套餐。我手头有太多别的事要做,而且还挺享受被5小时窗口拦住的感觉——这东西太容易上瘾了。后来我学会了一招:代币用完的时候输入!sleep 3h(或随便多久),再按Ctrl+B把它放到后台运行(不然会有2分钟超时)。几个小时后Claude会自己醒来,额度重置后继续干活,哪怕我人不在旁边。

让它把活干好

定制的快照测试工具

LLM编程的情况下,那些长期以来被认为是好实践的东西变得更有价值了。比如严格配置的类型检查和100%测试覆盖率——关于为什么“100”这个数字特别神奇,参见Jonathan Lange的Galahad原则。

这些给智能体提供了基本的反馈回路,而它们现在也相当擅长对这些反馈做出合理的响应。不过,如果你不主动要求,它们还不会自己去搭这些东西。至少现在不会。

我曾在前端开发团队做过几年管理和编码工作,虽然我们做了很多好事,但始终没真正落实快照测试。而我一直想试试。

所以,比较早的时候,Claude就给Toucan做了一个工具:用无头浏览器给应用的每个页面截图。这真的非常有用——一方面它是集成测试,另一方面它能用来检查设计,还能让我自己做设计QA。它有一个给我看的网页视图(给LLM看的是JSON)、集成的像素级diff、大量筛选和视图选项、基础性能测量,还有命令行开关可以对另一个分支做快照对比。

这简直是无价之宝。

最终的结果是,我让代理去做的事,几乎都能直接完成。不过它通常会做一些我不喜欢的外观设计,或者把部分交互体验弄乱。有时候我还得跟它争论数据结构,或者争论系统里缓存该放在哪儿。

但总的来说,代码它是真的能写出来,而且不会弄坏别的东西。现有测试照常通过,新测试也会补上。它干起活来就像一个效率极高的资深软件工程师,只是上下文感知能力比较差——想要那方面也合格,恐怕得等到 2027 年底或 2028 年。去年的时候,我打心底里不觉得它能把编码做到这个水平。

我遇到过一个比较严重的 bug。有个给列表重新排序的新功能,我从来没测过。某天在外面,我在手机上按了一下,结果整个列表连同里面的内容全被删了!问题出在本地优先存储引擎的数组操作写错了。后来代理帮我恢复了数据,加上了各种日志功能,方便查看同步时到底发生了什么,还更新了文档,明确写着别再犯同样的错误。

最后,我听了 Jyn 的建议,加了一个自我改进的反馈循环。我的版本很粗糙——在 AGENTS.md 里加一段提示,让代理把任何让它费劲的事记到 SELF-IMPROVE.md 里,同时统计同一个问题出现的次数。我会查看这些记录,判断哪些值得处理,然后安排改进。

这个方法挖出了不少问题,比如快照视觉不稳定、node_modules 频繁变动(代理会反复尝试绕开)、性能问题、缺少工具等等。这套机制虽然还非常原始,但我估计未来几年我们都会花大量时间盯着这类东西——这就是所谓的「AI 开发者体验」。

重构

出于对国际标准和简洁性的执念,我一开始想用 Web Components 和原生 JavaScript 来做。我原本希望 Toucan 平台本身能足够强大,让每个应用都变成很短的、单一的 HTML 文件。结果没走通,后来我意识到代码越来越乱,而且有了大语言模型之后,构建步骤其实又便宜又简单,于是我们做了两次大重构。

一个是迁移到 TypeScript,另一个是迁移到 Preact(一个更轻量的 React 替代品)。两次都很顺利——快照测试帮忙确保了没有任何东西被破坏,事实上也确实没有。重构之后一切仍然像素级一致。不过,我并没有花太多时间手动检查代码质量——见下一节。

最初的图形设计相当粗糙。我花了很多力气才让它升级设计,不过最终还是做到了。我不得不强迫它正确地提取共享组件。一个设计能力比我强的人应该能把它做得非常好。不过,跟我自己动手做出来的东西相比,已经算很出色了。

未来

三个功能完整的移动应用,加上桌面版本。坦率地说,能用这么少的力气做出这么精致的东西,实在令人惊叹。

它们已经接近可供其他人使用的程度了,甚至有点危险地接近。如果这些是五年前我写的,我肯定会去推广它们,努力获取用户。

不过现在,这感觉有点……让人疲惫?这些应用对我来说有点太 vibe coding 了。安装和设置都有点古怪。它们做的事情也有点过于定制化。

对我来说,悬而未决的问题是:在一个智能体编程的世界里,大型协作开源项目该如何运作?我真正想要的是,让任何人都能轻松制作属于自己的、有状态且可同步的定制应用。这感觉很难,原因如下:

  1. 用户体验和产品反馈是一项技能,而且仍然很难做好。人们对移动应用的期望很高,我觉得很少有人愿意去经历必要的反馈迭代过程。

  2. 跨平台应用框架仍然相当笨重。在 Web 和移动端都好看的界面组件库很有限,PWA 对终端用户来说也不熟悉,编写多个应用需要专业技能,而且难以部署。

  3. 我并不真正觉得自己拥有这个产品。如果我在经营一家公司,这倒不是大问题。但我并没有仔细审查过代码——我也没必要这么做。在这个世界里,人们对开源有什么期待?我们如何让别人知道这是一个有质量、会持续维护的东西?我已经习惯了代码是开源中交付的关键部分。

  4. 本地优先(local-first)至今没有一个标准化的平台。可以想象这样一个世界:拥有一个能本地优先同步的个人数据存储库,就像拥有电子邮箱地址一样稀松平常。但现实并非如此。要在2026年推动这件事落地,该怎么做还不清楚——仅仅把它开发出来,已经不再是什么亮眼的成绩了。

查看原文