系列目录(4 篇已发布)
第一季 · 开始之前 · 第 1 篇
我用 AI 从零做了一个全栈产品
人和 AI 怎么分工,以及 AI 做不好的是什么。
去年八月,我决定做一个求职工作台。
不是练手项目。它要真的上线,真的给我自己用,真的处理一百多条投递记录。
问题是,只有我一个人。
前端、后端、数据库、浏览器插件、部署、运维,全是我。按以前的节奏,这种项目做到一半就会停——不是因为难,是因为事情太多,每次捡起来都要重新回忆上次做到哪。
这次我做完了。方法不是“让 AI 写代码”这么简单,而是把开发过程拆成了一套 AI 能执行、我也能验收的流程。
先看结果。
一、做了什么
一个求职工作台,公网运行,自己秋招一直在用。
- 30 个数据模型,29 次数据库迁移,94 个服务端接口。
- 10 个工作台页面,Nuxt 4 全栈,PostgreSQL。
- 一个 Chrome 网申插件,73 条填写规则,162 条测试。
- 部署在一台 2 核 2G 的服务器上,Docker Compose 三个容器。
开发过程留下了这些痕迹:
- 56 份 Feature Spec,56 份实施计划,57 份任务清单。
- 69 次提交。
- 任务清单里有执行记录,最多的一天写了 31 条。
下面讲我是怎么和 AI 分工的。
二、分工
一句话:AI 产出候选答案,我决定哪个答案能进代码库。
| 我负责 | AI 负责 |
|---|---|
| 决定做什么、不做什么 | 把决定写成文档 |
| 数据模型、接口契约 | 按契约生成 schema、路由、类型 |
| 验收标准 | 写实现、写测试、写说明 |
| 读 diff、定位问题 | 跨文件搜索与批量修改 |
| 判断“这样对不对” | 给出三五种做法和各自的代价 |
这条分工不是一开始就有的。最初我也试过“帮我做一个求职管理系统”,结果它给了我一个看起来专业、但完全不懂我业务的架子:用户表、岗位表、投递表,每张表都有软删除和时间戳。
它没有写错。它只是不知道:岗位是全局共享的事实,而“我不合适”是我个人的判断;三个月前投出去的简历,今天必须能原样打开。
这些判断只能由我做。AI 的价值在于,当我把判断说清楚之后,它能很快把它变成代码。
三、一天怎么过
一个功能通常这样走:
- 我写一份 spec,说清楚目标、场景、范围、不做什么、验收标准。10 到 30 分钟。
- 让 AI 读 spec 和现有契约,生成一份 plan,写架构、顺序、风险和验证方案。
- 让 AI 把 plan 拆成任务,每条任务只描述一个结果和验证方法。
- 一次只做一条任务。做完一条,先在本地跑验证。
- 我读 diff。重点看它有没有改到任务以外的地方。
- 把验证结果写回任务清单,再开始下一条。
这套流程在仓库里是四个命令:
/spec 需求 → specs/features/F-XXX-<slug>.md
/plan spec → plans/F-XXX-<slug>.plan.md
/tasks plan → tasks/F-XXX-<slug>.tasks.md
/verify 对照验收标准逐条检查
命令本身很短。比如 /spec 的全部内容是:
1. 分配下一个 F-XXX 编号。
2. 写入 specs/features/F-XXX-<slug>.md。
3. 必须包含目标、用户场景、范围、不做什么、验收标准、受影响契约与开放问题。
4. 不明确且会改变范围、数据、隐私、成本的事项必须先提问。
5. 完成后只请求确认,不实现代码。
关键在最后一句:不实现代码。
AI 很容易在“确认需求”的时候顺手把代码写了。一旦这样,后面所有讨论都变成对既有实现的辩护,而不是对需求的判断。
一个最小的例子
简历要导出成固定 A4 排版的 PDF。
我给的约束有三条:页面尺寸固定;分页不能把一段经历切断;中文字体要嵌入。
AI 的第一版方案是用 CSS 的 @page 加 print 媒体查询。看起来对,实际不行:浏览器打印的分页由渲染引擎决定,我控制不了“这一段必须整体移到下一页”。
第二版改成用 playwright-core 渲染 HTML,再导出 PDF。这一步它做得很好:等待字体加载、设置页面尺寸、打印背景色,都是现成的 API。
验收方式是看三件事:导出的 PDF 页数是否等于预览页数;每页底部有没有被切掉的半行字;中文有没有变成方框。
三件事都过了,这个功能才算完成。
四、AI 最擅长的三件事
第一,样板代码。
表单、列表、分页、错误处理、CRUD 路由。这些东西有固定形状,AI 写得又快又稳。94 个接口里,大部分骨架是它生成的。
第二,跨文件改造。
改一个字段名,它能在几分钟内找出所有引用:Prisma schema、Zod 契约、服务层、路由、页面、测试。手工做这件事要半天,还容易漏。
第三,写测试和文档。
把一段行为翻译成断言,是 AI 的强项。我的插件测试从 0 写到 162 条,大部分是它起的草稿,我补边界。
五、AI 最不擅长的三件事
第一,判断该不该做。
你问“要不要加一个自动投递功能”,它会给你一套实现方案,还会告诉你这是“提升用户体验的关键功能”。
它不知道的是:投错岗位比没投更糟,平台条款和账号风险不在我手里,而且提交前的核对本来就是必要步骤。
这类判断,它给不了。
第二,跨会话的一致性。
今天加的字段,明天它可能忘了写迁移;今天定的状态枚举,后天它会在另一个文件里再抄一份。
模型没有“上次我们说过”的长期记忆。所以规矩必须写在文件里,不能只留在对话里。
第三,真实环境验证。
它经常说“已完成”“已验证”。但你去看,它只是把代码写完了,没跑过构建,也没在浏览器里点过。
有一次它报告“lint、typecheck 通过”,我去跑,发现它只跑了其中一个命令。从那以后,验证结果必须由我复跑一遍,并写进任务清单。
第四,它会悄悄扩大范围。
你让它修一个字段的显示问题,它顺手重构了整张表;你让它加一个只读接口,它把写接口也补上了。
它不是在捣乱,它只是觉得“既然都来了”。所以任务清单里必须写清楚“这条任务只做什么”,diff 里超出范围的部分要退回。
六、所以流程比模型重要
同一个模型,有没有下面这几样东西,产出质量差一个量级:
- 一份说明“什么算完成”的验收标准;
- 一份说明“数据长什么样”的契约;
- 一条一次只做一件事的任务清单;
- 一个能跑起来的验证命令。
没有这些,AI 会不断给你“看起来对”的代码。有了这些,它至少知道自己错在哪。
七、一个具体的教训
最后悔的,是没有一开始就把真实页面做成测试夹具。
插件的表单识别改了五轮。每一轮都是:用户反馈填错了,我去看页面,改规则,然后等下一次反馈。
直到我把两份真实的页面结构导出成 JSON,写成回放测试,情况才变。改规则之前先跑一遍夹具,改完再跑一遍,能立刻知道有没有把别的字段弄坏。
这件事 AI 帮不上忙。它不知道真实页面长什么样。真实世界的样本,只能由人收集。
八、这个方法不适合谁
说三点实话。
第一,如果你不打算读代码,这套方法会更危险。AI 会写出能跑的代码,也会写出你不知道为什么能跑的代码。出问题时,没人能修。
第二,如果项目只做一次、不维护,写 spec 和任务清单的时间可能不划算。我的项目要长期用,所以这笔投入能摊薄。
第三,如果你不能接受“先写文档再写代码”,这套流程会很难受。它确实更慢,尤其是在你已经想清楚怎么做的时候。
我自己的体会是:AI 把“写”的成本降得很低,于是“想清楚”变成了瓶颈。 这个系列后面每一篇,基本都在讲我怎么把一件事想清楚,然后交给它。
下一篇:先立规矩,再让 AI 写代码