分享用 Next.js、FastAPI、Supabase、Stripe、Clerk 等整合现代 AI 的单人全栈产品实战,重点讲述技术选型和集成踩坑。
过去几个月里,我利用夜晚和周末时间,独立开发了 Reclaim——一款面向工程师的 AI 求职 Agent。它会读取你的 résumé,给出诚实的评分,并将你的经历与真实开放职位进行匹配。目前已经在 reclaim.careers 上线(可免费扫描,无需注册)。
这不是一篇产品发布帖,而是对整个技术栈的拆解,更重要的是,我会讲讲那些曾经出过问题的地方。下面就是它的实现方式。
Frontend——部署在 Vercel 上的 Next.js。 使用 App Router,并在适合的地方采用 server components。选择 Vercel 托管,是因为代码推送后自动部署的流程几乎没有摩擦。作为独立开发者,我优先考虑的是开发速度,而不是对基础设施的控制权。
Backend——部署在 Render 上的 FastAPI。 我没有把所有东西都塞进 Next API routes,而是将 Python 后端单独拆了出来,因为 résumé 解析、匹配 pipeline 和数据抓取这些重活本身更适合用 Python 完成,同时我也希望它们与前端的请求生命周期相互隔离。
Database——Supabase + Prisma。 底层使用 Postgres。Prisma 负责 schema 和类型安全查询;Supabase 则提供托管的 Postgres,以及一些与 auth 相关的数据能力。
Auth——Clerk。 它负责注册、session 和整个身份层。后面还会详细讲 Clerk,因为我在这里浪费的时间最多。
Payments——Stripe。 使用 live mode,提供带试用期的不同订阅层级。webhook 通过 lookup keys 解析订阅层级,因此调整定价时不需要修改代码。
真正的“AI”——Gemini。 这是最有意思的部分,所以值得单独展开。
我最看重的一点是:这里的 AI 并不是附加在产品旁边的一个 chatbot。真正的产品决策由 Gemini 完成。
**Résumé 阅读:**解析 PDF、提取真实结构并进行评分——判断依据不是关键词密度,而是其中的表述能否得到事实支撑。整个产品的前提就是诚实:大多数 AI résumé 工具会堆砌关键词来绕过 ATS,但当你进入面试、无法为自己 résumé 上的内容提供佐证时,这种做法马上就会适得其反。Reclaim 采取了相反的方式——它会指出你真正有优势的地方,以及哪些表述有些言过其实。
**匹配:**将 résumé 与 3,000 多个真实开放职位组成的语料库进行匹配评分。这些职位抓取自数百家公司的招聘网站,包括 Greenhouse、Lever、Ashby 和 Workday,并呈现你的真实技能与哪些岗位相符,以及申请哪些岗位可能有些勉强。
有一个实际的工程决策是:我会根据不同任务所需的推理量,将它们路由到不同层级的 Gemini model,以便把单个用户的成本控制在合理范围内。免费扫描使用成本更低、速度更快的 model;较重的解析和匹配工作则使用能力更强的 model。每位用户完成一次完整 onboarding 的成本约为 5 美分,这意味着成本从来都不是限制因素——真正的问题是分发和转化率(这个教训本身就值得单独写一篇文章)。
Clerk webhook 的尾随换行符 bug。 切换到生产环境后,webhook 的签名验证悄无声息地失败了。原因是 signing secret 写入环境变量时,末尾多了一个换行符。逐字节看,这个 secret 似乎完全正确;实际上并不是。一个肉眼看不见的问题浪费了我好几个小时。教训是:当签名验证失败,而 secret “看起来没问题”时,首先检查空白字符。
webhook 路径上的 P2002 唯一约束冲突。 多个堆积的 webhook event 同时尝试创建同一条用户记录,触发了 Prisma 的 unique constraint。最终只能让 handler 具备幂等性——使用 upsert 语义,而不是直接、天真地执行 create。
一次无声的资金泄漏。 有一条评分路径会为无权使用该功能的用户调用 Gemini——API 费用花在了那些永远不会付费的人身上。它“运行正常”(没有错误,输出也正确),这恰恰是它危险的原因:除了查看日志和账单,没有任何东西会暴露这种成本 bug。后来我把它放到了 entitlement check 后面。教训是:一个能够正常工作、但本不该运行的功能,就是一种会持续花钱、却不会抛出任何错误的 bug。
把 Python 单独拆出来。 如果你的 AI 工作天然适合 Python,就不要强行把它塞进 JS framework 的请求周期。虽然多了一个部署目标,但单独设置 FastAPI service 是值得的。
Lookup keys 优于硬编码的 price IDs。 Stripe 的定价变化不应该要求重新部署。
最可怕的 bug 是那些不会抛出错误的 bug。 尾随换行符、成本泄漏和 race condition——它们看起来都能“正常工作”。阅读日志和账单,才能发现 error handler 捕获不到的问题。
成本并不是最难的部分。 每次 onboarding 的成本约为 0.05 美元,真正的问题从来不是 AI 账单,而是如何让合适的人来到网站。构建产品只是最容易的那 20%。
如果你想亲自看看,它已经在 reclaim.careers 上线——résumé 扫描完全免费,也不需要注册。如果你对这个技术栈、Gemini 路由策略或数据抓取有任何问题,我都非常乐意在评论区回答。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。