用四个 Claude Code 技能搭建完整 SaaS
作者称借助四个可复用的 Claude Code 技能,将一页需求逐步转成包含认证、日历、支付和 AI 聊天的 SaaS,并公开相关技能。后端集中使用 Neon,多项服务依赖提前获得的私有预览权限。
完整中文译文
pastmonday.com 已经上线。它有身份认证、周历、通过 Stripe 实现的分级计费、推荐奖励额度、文件上传,以及了解你日历内容的 AI 聊天功能。这是一个小而完整的 SaaS,放在以前,通常得花三个月才能做出来。
它有两个不寻常的地方,也是我写这篇文章的原因。
第一:它不是我手写的,而是一座软件工厂造出来的。四个可复用的 Claude Code skills,把一页产品简述分阶段变成已经上线的产品。我最近在 YouTube 上聊过这件事,这些 skills 本身也已经在 GitHub 上公开。
第二:看看它的供应商名单。Postgres 用 Neon,Auth 用 Neon,数据 API 用 Neon,对象存储用 Neon,LLM 调用也经过 Neon。Stripe 负责收款,我自己的集群负责运行容器,名单就到这里。整个后端只有一家供应商。而就在几周前,这句话还说不出口,因为其中一半服务当时根本不存在。
Neon 宣布,他们正在打造完整的后端:Postgres、Auth 和 Data API 已经正式可用(GA),Object Storage、Functions 和 AI Gateway 则刚进入私有预览。我拿到了抢先体验资格,让工厂用上这些服务,这篇文章就是构建报告。
说明:这篇文章由我关于软件工厂的视频转录而来,经过 AI 处理,并做了适合阅读的编辑。如果你更喜欢看视频,内容在这里:
▶ 观看:软件工厂让人害怕,但确实可行,而且很容易上手
一座软件工厂,由四个可复用的 Claude Code skills 读取同一份 PROJECT.md 产品简述,在大约 40 分钟内,把 pastmonday.com 从空仓库推到了生产环境。
整个后端都用 Neon:Postgres、Auth 和 Data API 已经 GA,Object Storage 和 AI Gateway 则处于私有预览阶段,我拿到了抢先体验资格。
资金和限额以服务端为准:用单条原子语句扣减配额,让 Stripe webhooks 保持幂等,并在每次调用前检查 AI 预算。
AI Gateway 的官方 SDK provider 当时还无法安装,于是 Agent 实际验证了兼容 OpenAI 的 endpoint,照样完成了上线。我在上一篇 Neon 文章中提出的 API-first 观点,再次得到了验证。
Neon 现在也为新服务提供了 Agent skills。工厂和平台正在靠拢。
视频:软件工厂让人害怕,但确实可行
GitHub 上的工厂 skills
pastmonday.com,已经上线的产品
Neon:我们正在构建后端
我的系列文章:如何构建任意 Web 应用
核心思路只有一个分工:skill 负责“怎么做”,产品简述负责“做什么”。
所有项目专属的信息,都放在仓库里的一份 PROJECT.md 中:名称、一句话介绍、套餐表、配色和字体、实体,以及启用了哪些服务。所有可以复用的内容,都放在 skills 里。想做另一个产品时,我就换一份产品简述。工厂本身不变。
整个过程分为四个阶段,每个阶段都是一个独立的 skill,都读取同一份产品简述:
基础阶段(set-project-structure)搭建骨架:采用约定目录结构的 Next.js 项目、Drizzle schema、带有取值来源注释的环境变量键、设计 tokens,以及每项已启用服务的占位客户端。这个阶段刻意少做:搭好衔接处,不实现功能。
落地页阶段(set-landing-page)负责审美。它研究产品简述中的参考网站,先写真实文案,再做布局,并严格遵守一份明确的禁用模式清单:不要渐变色首屏,不要“Supercharge your workflow”这种文案,不要虚构的用户评价。
后端阶段(set-app-backend)负责正确性,也就是资金和限额。每一份配额、奖励额度、token 预算和每一美元,都必须由服务端以原子、幂等的方式执行约束。后面会详细讲,因为 Neon 的新服务就是在这个阶段接入的。
Dashboard 阶段(set-dashboard)构建用户日常使用的应用界面:日历、弹窗、流式 AI 聊天,而且只使用第三阶段提供的接口契约。
每个阶段都会在动手构建前停下来,等待审批;会核实当前的软件包版本,而不是相信训练数据;结束时必须让仓库保持可交付状态。不能留下做了一半的部分,也不能说“以后再打磨”。
可以在这里逐个点开这些阶段。这就是构建 pastmonday 时实际运行的流水线:
▶ 软件工厂流水线(交互式):交互组件可在原文中运行。
此前我已经详细写过前三个阶段。如果你想深入了解,可以阅读关于概念、产品简述和落地页的文章。
这篇文章真正关心的是:这种工厂能做到什么程度,取决于它所依赖的平台接口。到了第三阶段,工厂必须接通身份认证、存储、数据访问和 LLM 调用,而供应商通常就是从这里开始越堆越多的。身份服务一家,存储桶一家,模型路由一家,再加上数据库。四个管理后台、四份账单、四套可能泄露的凭据。
这一次,这四处衔接都落在了同一个平台上。
下面是 pastmonday 实际使用的服务,以及各部分所处的状态:
先拿代码库里的几处实现作证,毕竟一句“能用”谁都会说。
Auth 自带 schema。身份信息存放在 neon_auth.user 中,而工厂的规则是:绝不复制一份。应用表通过外键直接引用它,因此不需要同步任务,不需要用 webhook 到处复制用户,也不会出现第二份权威数据源:
// Neon Auth's identity schema, referenced, never mirrored
export const neonAuth = pgSchema("neon_auth");
export const authUser = neonAuth.table("user", { id: text("id").primaryKey() });
// profiles FK straight into it
userId: text("user_id").notNull()
.references(() => authUser.id, { onDelete: "cascade" }),
Storage 兼容 S3,因此不用再学一套专有 SDK。客户端就是普通的 AWS SDK,它会自动从 AWS_ENDPOINT_URL_S3 读取 endpoint。上传使用预签名 PUT,对象键按用户划分作用域。由于预签名 PUT 无法强制限制文件大小,确认路由会执行 HeadObject,并删除所有超限文件。有意思的是:Neon 的存储会随数据库一起创建分支。每个分支都有自己隔离的存储状态。不同环境中的文件和数据行,终于不会再各走各的了。
AI Gateway 用一个 API 接入 Anthropic、OpenAI、Google 等厂商的模型,提供逐请求日志和速率限制。它运行在同一套网关基础设施上,据 Databricks 称,这套基础设施每月处理 125 万亿个 tokens。对应用来说,这意味着环境变量中只需要一个 token,不用再攒一抽屉模型厂商的密钥,而模型只是一个配置值:
const provider = createOpenAICompatible({
name: "neon-ai-gateway",
baseURL: `${NEON_AI_GATEWAY_BASE_URL}/ai-gateway/mlflow/v1`,
apiKey: process.env.NEON_AI_GATEWAY_TOKEN,
});
export const chatModel = provider(process.env.NEON_AI_GATEWAY_MODEL);
可以在这里探索实际架构,每个方框都能点击:
▶ pastmonday 的后端,全部使用 Neon(交互式):交互组件可在原文中运行。
在上一篇 Neon 文章中,我提出过一个观点:Neon 采用 API-first 的方式,所以一项底层能力刚出现,Agent 就能调用,不必等到有人为它做出一个按钮。我当时构建了一个 Neon 尚未推出的功能,证明了这一点。
这次构建在两个地方,把这个想法推进到了超出我预期的程度。
第一,AI Gateway 实在太新了,工厂运行第三阶段时,它的官方 AI SDK provider 包甚至还无法安装。换成人,很可能就停在这里了。但 Agent 没停:它探测了网关,在 /ai-gateway/mlflow/v1 找到兼容 OpenAI 的 endpoint,发出真实请求完成在线验证,然后改用 AI SDK 通用的 OpenAI-compatible provider 接通了应用。代码中留了一条注释:“等官方 provider 可以安装后再替换。”这就是 API-first 带来的好处:endpoint 已经存在,缺一个软件包也不妨碍继续。
第二,是我没预料到的双向靠拢:我发布工厂 skills 一周后,Neon 也发布了自己的 Agent skills。这些指令文件教编码 Agent 如何集成 Functions、Storage 和 AI Gateway,一条命令就能安装:
npx skills add neondatabase/agent-skills
站在我的位置,再读一遍这件事。我写 skills,教 Agent 如何构建产品。现在 Neon 也写 skills,教同一个 Agent 如何使用他们的平台。工厂和平台正在中间会合,而且双方都不需要征得对方同意。当一家供应商把 Agent 当作主要开发者时,事情就会变成这样。
一座交付精美却有缺陷的应用的工厂,只会成为负担,所以第三阶段从设计上就格外谨慎。pastmonday 要收费,也要按限额出售服务:Free 套餐提供 1 条日历条目和 5,000 tokens 的 AI 预算,Pro 套餐每个周期提供 10 条日历条目和 20,000 tokens,Max 则不限量。限额只有在并发请求无法绕过时,才有意义。
一个约束让这次的要求比平时更加严格:工厂通过 Neon 的 HTTP driver 使用 Drizzle,而这个 driver 不支持交互式事务。不能先 BEGIN,持有锁,作出判断,再 COMMIT。因此,每个涉及资金的关键操作,都必须变成一条原子语句。下面就是实际的条目创建逻辑:一次往返,同时完成配额检查和插入:
WITH consumed AS (
UPDATE billing
SET used_this_cycle = CASE WHEN used_this_cycle < monthly_quota
THEN used_this_cycle + 1 ELSE used_this_cycle END,
extra_credits = CASE WHEN used_this_cycle >= monthly_quota AND extra_credits > 0
THEN extra_credits - 1 ELSE extra_credits END
WHERE profile_id = ${profileId}
AND (used_this_cycle < monthly_quota OR extra_credits > 0)
RETURNING id
)
INSERT INTO calendar_entries (user_id, title, ...)
SELECT ${userId}, ${title}, ...
WHERE EXISTS (SELECT 1 FROM consumed)
先消耗配额,再消耗额外额度;两者都没有,就不插入任何内容,并向调用方返回 402。两个并发请求不可能同时拿走最后一份额度,原因不在于代码写得多小心,而在于这条语句无法被拆开执行。
同样的谨慎贯穿其他部分:每次调用网关前,服务端都会检查 AI 预算,并在调用完成后按真实用量计量;Stripe webhooks 在 processed_stripe_events 台账中按 event id 去重,确保重放事件不会重复发放额度;配额耗尽时会返回带明确类型的 402,UI 会将它转成升级提示,而不是错误 toast。
这些都不是 Neon 专属的做法,但这是工厂坚持的标准,而新服务顺利融入了这套标准。后端平台真正要经受的考验,是执行约束的那些路径,而不只是演示效果。
我一直最喜欢的 Neon 底层能力是分支。我做过这样的预览环境:每个 pull request 都有自己的数据库分支,由 Agent 通过 API 创建和销毁。
新服务把这个思路扩展到了数据库之外。现在,存储状态已经会随数据一起创建分支,而 Neon 通过与其他服务相同的 CLI 和 API 管理 Functions。方向很明显,他们也已经明确说了出来:分支应该复制整个后端,而不只是 schema。
对软件工厂来说,这就是缺失的那一块。如今,我的工厂流水线会在它构建的、形态接近生产环境的环境中验证每个阶段。我想要的下一个版本是:每次工厂运行、每次 Agent 会话、每次实验,都能获得一份完整、隔离的后端副本,包括数据行、文件和函数。它只在任务期间存在,任务结束后就消失。数据库分支已经在 schema 变更中证明了这种工作流的价值。把它扩展到整个后端,就能把“启动一个预发布环境”从半天的 Terraform 工作,变成一次 CLI 调用中的一个参数。
这和我上一篇文章中的 spending-caps 功能是同一个故事。顺便说一句,它现在仍然标着“coming soon”,我也还在等他们兑现:底层能力先通过 API 交付,基于它们构建产品的人,就能跑在路线图前面。
这套技术栈的卖点,并不是“Neon 什么都做”。它的主张更具体,也更实在:一个功能完整、可以正常运行的 SaaS,涵盖身份、数据、文件、AI 和收款,现在只需要一份产品简述、四个 skills、一家后端供应商和一个 Stripe 账户。pastmonday 从空仓库到在我的集群上进入生产环境,大约用了 40 分钟。而其中大部分时间,我都在审批关卡作审美取舍,并没有忙着做集成。
如果你想继续深入:视频讲解了工厂的概念,GitHub 上的 skills 可以直接拿去用,系列文章逐个介绍了每个阶段,而 pastmonday.com 就是活生生的证明。去创建一条日历条目吧,你点击触发的,就是一次能抵御竞态条件的原子配额扣减。
如果你在 Neon 工作:请把“分支复制一切”的未来做出来。我已经有一座工厂在等它了。
如需进一步采取措施,你可以考虑屏蔽此人和/或举报滥用行为。