LLM擅长在已有清晰架构边界和丰富示例的成熟技术栈上生成代码,但起点越差输出越差;强调了设计能力不可外包。
应用的基础至关重要,尤其是在你使用 Agent 来写代码的时候。
每个人都在谈论 AI 和机器学习中的"垃圾进垃圾出",但当你去把整个代码库交给一个 LLM 并让它开始构建时,没人真正谈论这意味着什么。LLM 本质上只是价值数十亿美元的模式匹配黑箱。如果你给它们一个易于理解的技术栈,有成熟的模式、大量文档、大量示例和清晰的架构边界,它们可以产生一些真正令人惊叹的结果。
如果你从零开始,或者更糟,从垃圾开始,它们往往会产生垃圾。
是的,Opus 5 和 GPT 5.6 Sol 确实能产生令人惊叹的输出。只要作为一个技术爱好者在 X 上稍作浏览就能看到。
但我并不想让我的整个开发过程依赖于"我可以永远向每个问题倾注无限 tokens"这个假设。
我想要一些我能理解的东西,如果我愿意的话可以手动编码的东西,以及一些拥有出色且广泛支持的东西,而不是定制或半定制的解决方案。再加上最近关于 AI 巨大成本的讨论——虽然我不认为我的编程 Agent 会消失——但它可能会从一把"代码霰弹枪"变成一个更精准的工具,只处理我真正不想亲自动手的任务。
作为开发者,我未来的工作是为 Agent 设计一个框,让它在最少的输入下做出好的决策。
这意味着选择我能理解的东西,理想情况下是流行的、非常适合我用例的东西,我能快速部署的东西,易于扩展的东西,以及 devops 开销最小的东西。一年后,当 Agent 生成了另外 3 万行代码时,我应该仍然能够查看这个技术栈并理解每一行代码。
我不会说这是最好的技术栈,但我会向你展示我是如何为每个项目选择技术栈的,我的决策逻辑是什么,以及为什么我认为这是最佳选择,特别是对于独立开发者或小团队。
这个应用本身叫 lyphe,是一个有明确主张的任务和生活管理应用,我主要是因为想要一个符合我思维方式的东西而构建它。它的核心仍然是一个相对简单的消费者 CRUD 应用——任务进入、任务被组织、任务有望完成——但有一些需求让架构变得更有趣。在初始原型阶段,我希望迭代尽可能快,所以在构建功能和 UX 时,我把它作为 PWA 使用。我希望更新感觉是实时的,我最终想要原生 iOS 和 Android 应用,原生功能如通知和 widgets 非常重要,我不希望移动端只是事后的想法。我也主要是在自己构建,编程 Agent 完成了说实话不负责任比例的实现工作,所以我选择的任何技术栈都需要是 Agent 和我都能有效工作的东西。
这给了我们一些非常有用的约束。
在我上一份工作中,CTO 和我同意的核心原则之一是,在基础设施方面,越少越好。我们是一个只有 4 个开发人员的小团队(包括 CTO),如果能自动化或外包基础设施,我们就会这么做。那是一家加密货币初创公司,所以运行 Avalanche 节点的 Linux 服务器是不可避免的,但我们的 API 运行在 Cloudflare Workers 上,数据库在 Supabase 上,我们的 NextJS 应用运行在 Vercel 上。如果能外包,就外包。
如果你能花钱让别人处理你的扩展和部署,特别是作为小团队或独立开发者,你就这么做。
虽然这不适用于你正在构建的每一个产品,例如在我目前的工作中,我们构建企业级 B2B 软件,需要 SOC2 合规和可选的本地部署,但当你在为自己构建应用或面向消费者的产品时,这是一个安全的赌注。
正因为如此,我变得非常喜欢 Supabase 和 Convex 这样的平台。
Convex 尤其是我最近的最爱,它是 NoSQL 和结构化数据的完美结合。数据结构和表在 TypeScript 中定义,然后自动转换为你的前端应用可以立即使用的 API。
而且它不仅仅是普通的 CRUD API——它是实时的。
所以如果你使用 Convex 为你生成的 hooks 来显示某些数据,数据在后端被更改时,它会立即在你的前端更新。所有这些只需要在你的应用中使用 Convex?

当你在用 Agent 开发时,这里还有另一个优势:Convex 大大减少了 Agent 实际上需要做出的架构决策数量。
你用 TypeScript 编写 schema。你的后端函数是 TypeScript。它输出面向前端的 API 接口——你猜对了,也是 TypeScript。它还自动处理迁移。
这减少了我需要考虑的东西,更重要的是,减少了我的 Agent 需要推理的东西。Convex 强加给我和我的 Agent 的那些约束,迫使我们都在它定义的规则内使用它,保持我们双方的高速运转,并减少 Agent 脱离轨道去决定重新发明 REST API 的可能性。
Convex 促使我学习了 Clerk。
Clerk 是一个与 Auth0 和 Stytch 非常相似的身份认证提供商,但 Clerk 有一些技巧,使其成为像我这样的独立开发者的理想选择。
前 5 万用户免费,如果你在拥有 5 万用户后还赚不到钱,你在干什么?
此外,他们通过 Stripe 提供计费服务,允许你直接在 Clerk 仪表板中管理用户订阅、应用功能和计费。这意味着你不需要搞 Stripe API,只需要调用 Clerk 来查看用户是否为功能付费。简单!
最后,也是我选择它们的主要原因,它们与 Convex 有超级紧密的集成,特别是因为我实际上是在阅读 Convex 文档中如何将我的应用与某种身份认证提供商集成时才发现 Clerk 存在的。
我不是处理密码的忠实粉丝。
在这个网络安全漏洞的时代,那只是我又一个必须担心的安全漏洞。
我能自己构建身份认证吗?
Agent 能为我构建身份认证吗?
当一个整个产品就是身份认证的公司会乐意为我做这件事时,我想让我们中的任何一个来负责把身份认证做对吗?
而且因为 Clerk 和 Convex 已经有紧密的集成,这甚至减少了 Agent 和我需要维护的代码。
对于前端框架,我总是默认为 React 或它的许多配套框架之一。我在一家加密货币初创公司在 Vercel 上使用 NextJS 工作了 4 年,那是一个我非常喜欢的技术栈——开箱即用的自动部署和预览链接,由于是 serverless 还能自动扩展。完整的 devops 胜利。然而,离开之后,我倾向于使用 Cloudflare 作为我主要的 serverless 托管提供商(我在那里也做了一些工作,因为我维护了大量基于 serverless Workers 的 API)。NextJS 在 Vercel 或纯 NodeJS 环境之外运行时有一些限制,这就是为什么它被 fork 成 OpenNext。这是一个更可移植、功能兼容的 NextJS 版本,可以部署到 Cloudflare、Netlify 和 AWS Lambda。它使用 Cloudflare Workers 作为其计算方法,允许静态和 SSR 页面。OpenNext on Cloudflare 将是我的前端框架。
好的,数据库、CRUD API、身份认证、前端框架和计费都已经处理好了。现在我们只需要一些组件。选择很简单——使用最流行的那个。当然是 shadcn——当前组件生态系统的王者。现在我可以无聊地简单样式化现有组件,还有大量兼容库可以用来毫不费力地改善应用的用户体验和动画。一个很好的例子是 animate-ui,我将在这个应用和下一个应用中大量使用它,因为它作为许多 shadcn 组件的完全替代品,同时增加了微妙的动画,让你的应用感觉独特和高端。
shadcn vs animate-ui buttons

最后,我正在构建的应用最终会是一个移动应用。我不想完全从头重写它,我只是一个有 AI Agent 的人!即使我能让 Agent 用感觉来构建一切,我真的不想长期维护 AI 生成的意大利面条式代码。
是的,Agent 让重写和维护大量代码变得更便宜。如果我真的想,我可以让 Agent 用 React Native、Flutter、Swift 或 Kotlin 重写整个应用。
但那样我就要维护两个仓库。这是我必须处理的更多事情,我必须考虑的更多事情。当 bug 可能存在于移动端、web 端或两者时,功能需要移植以保持 parity。我要处理的事情太多了。
我宁愿为 web 和移动应用使用单一代码库,用一种我非常熟悉的语言,用一个我选择的技术栈。所以移动端移植留给我的两个真实选择是:Capacitor 和 Tauri。
我是 Tauri 的忠实粉丝。它是 Electron 应该成为的样子,一个超 minimal 的运行时,使用你操作系统的原生 webview 能力,结合编译的 Rust 后端,实现闪电般的原生交互。我构建了一些 Tauri 应用,包括最近我为 macOS 构建的改进版系统指标分析器,我叫它 computer-state。我最喜欢的语音转文字应用 Handy 也是用 Tauri 构建的。随着 2024 年 Tauri 2 的发布,它正式支持 iOS 和 Android 作为部署目标。然而,有一个问题,技术栈成熟度。即使已经两年了,没有很多插件、文档或关于如何有效开发移动端 Tauri 的信息。你在网上找到的大多数包、文章和信息仍然主要针对桌面应用,当你需要桌面应用时这很棒。但我想要一些成熟的东西,一些我能找到大量文档和插件支持的东西。所以我要用 Capacitor。
Capacitor 是移动应用的旧 Apache Cordova 系统的重写。虽然概念上相似,但 Capacitor 更好地为处理原生 Swift 和 Kotlin 集成而构建,用于构建你自己的插件或使用现有插件将你的 webview 应用扩展为原生功能。这对我来说非常重要,因为构建这个应用的核心想法之一是我希望 widgets 让我保持正轨,不断提醒我需要完成什么。你不能用 React Native 或纯 web 应用构建 widgets。你可以用 Scriptable 为 iOS 原型化它们,但我们可以改天再谈。这是一个我做的 scriptable 原型示例。

虽然我还没有开始 Capacitor 集成,但当真正开始做的时候,大部分工作可能可以通过我的一些严格指导由 Agent 自己处理,因为很多系统集成以及 widget 创建都有很好的文档记录,并且会有大量示例代码可以参考。而且因为这可以简单地作为 OpenNext 应用的移植,某些页面是 SSR 需要一些小的更改,它将与 web 上看起来完全一样,拥有所有相同的功能。
我提到我正在使用 Cloudflare Workers 来部署应用的 OpenNext 部分,但我没有使用 Cloudflare 自己的构建系统。对于这个应用,我决定通过使用 GitHub Actions 来给自己更多的控制和自主权。这样我们可以在一个地方构建和部署所有东西:OpenNext、Convex,以及(最终)移动端移植。