恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
用Claude Code开发宠物生命周期管理App:从零到可运行MVP的实战记录
首页
资讯中心
/
用Claude Code开发宠物生命周期管理App:从零到可运行MVP的实战记录
用Claude Code开发宠物生命周期管理App:从零到可运行MVP的实战记录
发布时间:2026/10/18 16:32:20
最近我用 Claude Code 把想了很久的一个小应用——宠物生命周期管理 App从完全空白的目录一直开发到能正常跑起来的 MVP。整个过程里最让我意外的不是 AI 能写出多少代码而是它把“杂乱想法到可运行软件”之间的翻译成本压到了极低同时把人类工程师的职责变得更像架构师和代码审查者。这篇文章不搞“10 分钟生成完整 App”的标题党也不打算吹 AI 万能。我想完整记录我从零搭建这个项目的全过程需求怎么拆、数据模型怎么定、API 和页面怎么迭代、提醒逻辑怎么处理以及我在每一步里踩过哪些坑。如果你也想用这类 agent 型编程工具搭一个自己的小项目这篇记录应该比官方示例更接近真实作战现场。不管你是想复刻一个同名应用还是打算用同样思路做自己的工具它都能提供一份可参考的作战手册。1. 先把业务拆明白宠物生命周期管理到底要管哪几件事很多人拿到一个想法后第一件事就是打开编辑器让 AI 写代码这是最容易翻车的姿势。AI 再聪明也猜不透你脑子里那个模糊的“宠物生命周期管理”到底包含什么。所以我的第一步不是开项目而是拿一张纸把业务拆清楚。1.1 核心场景与功能清单我梳理下来宠物生命周期管理主要围绕几个高频场景宠物基础档案名字、物种猫/狗、品种、生日、性别、照片、备注。生日这事看似简单但它是后续所有“生命周期”计算的起点。疫苗管理首次接种、年度加强针不同疫苗的间隔期不一样。驱虫管理体内驱虫和体外驱虫是两套节奏周期也完全不同。定期体检健康成年宠物一般半年到一年一次老年宠物频率更高。日常健康记录体重变化、就诊记录、症状备注这些散落信息需要一条统一的时间线。生命周期阶段判断幼年、成年、老年对应不同的护理重点系统可以根据生日自动提示。这里每一条都能再往下钻出很多功能比如疫苗电子证、医院共享、多宠物家庭、用药提醒、费用统计……如果全堆进第一版项目大概率烂尾。1.2 先做什么不做什么MVP 的边界我给自己定的 MVP 原则是数据能闭环、提醒能滚动、时间线能记录。具体来说分成三档范围功能点理由MVP 必做宠物档案增删改查、列表与详情页一切业务的数据地基MVP 必做循环提醒疫苗/驱虫/体检、今日待办仪表盘这个 App 的核心价值不能让用户靠脑子记MVP 必做健康时间线体重、备注、事件记录让“状态变化”有地方落二期再做图片上传、疫苗电子证、多宠物对比报表依赖外部存储或更复杂的前端一期先不碰暂时不做用户登录、多用户权限、云端同步单人本地使用场景登录只会拖慢开发节奏这个表格我建议你也给自己写一份。AI 编程工具最大的问题不是写不出代码而是会不加判断地帮你做出超出范围的功能。你越早划定边界它跑偏的概率越低。1.3 技术栈选型为什么是单体全栈而不是前后端分离技术栈的选择直接影响后续和 AI 协作的顺畅程度。我最后选了 Next.js TypeScript Prisma SQLite 这套组合理由很简单它们都适合“AI 对话式开发”。Claude Code 这类工具在单体结构里表现最好。所有代码都在一个目录树里AI 改完页面改接口、改完接口改数据库模型不需要在两个仓库之间反复跳转。前后端分离的项目我也试过让 AI 同时维护两个项目会导致上下文割裂经常出现“前端调用的字段和后端返回的字段对不上”这种问题。下面是几个方案的对比都是我实际体验后的感受方案结构AI 协作体验适合场景Next.js Prisma SQLite单体全栈文件路径清晰好一个目录管全部上下文集中个人项目、MVP 最快路径Express React/Vite前后端分离需要双仓库一般改一次功能要跨项目操作有完整前端团队或既有后端FastAPI Vue前后端分离后端逻辑重中等接口清晰但两端同步成本高业务偏数据计算、AI 模型服务Flutter移动端体验好编译链复杂中等预览调试不如浏览器直接原生移动端诉求强烈开发期用 SQLite 是我强烈建议的选择。零配置、单文件、随时能看数据等真要部署上线再切更重的数据库也不迟。这段时间的体验下来这个选型让 Claude Code 的代码生成准确率高了不少因为它见过的同类型项目模板足够多生成的代码风格和目录结构都很标准。2. Claude Code 开工从空目录到可运行骨架的三条路径业务拆清楚了技术栈也定了接下来才真正进入“用 Claude Code 从零搭项目”的部分。我试过三种启动方式各有各的坑。2.1 路径一用脚手架初始化再交给 AI 改造推荐第一种方式是先用官方脚手架把项目骨架拉起来再启动 Claude Code 进行后续开发。比如创建一个带 TypeScript 的 Next.js 项目我实际跑的是类似下面这条命令npx create-next-applatest petlife --typescript --app --tailwind --no-src-dir命令跑完后你会得到一个干净可运行的基础项目。这时再启动 Claude Code让它先熟悉项目结构然后开始加 Prisma、建表、写接口。为什么推荐这条路因为 AI 的知识有“截止日期”。像 Next.js 这种迭代快的框架AI 记忆里的版本可能已经过时你让它直接生成一个完整项目很容易出现依赖版本冲突或目录结构不对。而脚手架保证了基础部分一定是最新最稳的AI 只需要在已有结构上做增量修改出问题的概率会小很多。2.2 路径二空目录里让 AI 从零生成我也试过在空目录里直接让 AI“创建项目”结论是能跑但很折腾。AI 会给你生成一套它认为合理的配置但依赖版本、配置文件细节、构建脚本这些地方十有八九要手动修几轮。一次两次还好如果是新项目光来回调试依赖就能耗掉大半个下午。这条路不是绝对不行当你要快速验证某个想法、不在乎技术债时依然有它的价值。但如果你要做的是一个会长期维护的产品我建议还是老老实实走脚手架路线。2.3 怎么让 Claude Code“先读懂项目再动手”这是我和这类工具协作时学到的第一课别上来就提需求先让它读项目。启动会话后我通常会这样发第一句话“先不要写代码。请完整阅读这个项目的 package.json、目录结构、配置文件然后告诉我这个项目当前的技术栈是什么、目录怎么组织的、有没有数据库层、已有哪几个页面。看完之后等我下一步指令。”这一步相当于让 AI 把项目上下文加载进自己的工作记忆。跳过这一步直接说“帮我加个宠物列表页”它可能不知道项目的路由风格、组件组织方式、是否已接入数据库生成出来的代码要么复用度低要么风格突兀。2.4 协作纪律一个会话只做一件事用 git 当存档点用 Claude Code 开发最容易犯的错误是“一个会话里塞太多任务”。我一开始嫌麻烦在同一个会话里既让它改档案页又让它加提醒逻辑还让它顺手调一下样式。结果 AI 改到后面忘了前面的约束把已经写好的接口又推倒重来了一遍。后来我给自己定了三条纪律每次会话只做一件完整的事比如“完成宠物列表页的 API 和页面”。每完成一个功能点立刻用 git 提交一次提交信息写清楚改了什么。会话进行中如果发现自己描述不清需求先停下来整理语言再继续对话。git 提交不仅是存档更关键的作用是给 AI 一个“安全边界”。反正随时可以回滚AI 的大胆尝试就有了兜底我审查代码时也不用担心一次改太多看不完。3. 数据建模阶段三张表把宠物生命周期钉死在代码里项目骨架准备好之后下一步是建数据库模型。很多人觉得数据建模是枯燥的准备工作但在我看来这是整个项目里最值得和 AI 深度对话的部分。因为所有页面交互、业务逻辑都建立在数据模型之上模型错了后面全错。3.1 Prisma Schema 长什么样我用 Claude Code 完成了第一版 Prisma 模型核心是三个实体宠物、提醒、健康事件。实际生成的 Schema 大致是这样model Pet { id String id default(cuid()) name String species String breed String? birthday DateTime? gender String? notes String? reminders Reminder[] events HealthEvent[] createdAt DateTime default(now()) updatedAt DateTime updatedAt } model Reminder { id String id default(cuid()) petId String pet Pet relation(fields: [petId], references: [id], onDelete: Cascade) type String title String intervalDays Int? lastCompletedAt DateTime? dueDate DateTime completed Boolean default(false) createdAt DateTime default(now()) } model HealthEvent { id String id default(cuid()) petId String pet Pet relation(fields: [petId], references: [id], onDelete: Cascade) eventType String recordedAt DateTime weightKg Float? note String? }你看这个模型宠物和提醒是一对多宠物和健康事件是一对多结构非常朴素。但朴素不等于简单这里面有几个设计决策直接影响业务能不能顺利跑起来。3.2 关键设计决策级联删除、可空字段、循环提醒的存储先说级联删除。onDelete: Cascade的意思是删除宠物时它名下的所有提醒记录和健康事件会一起被删掉。这里我和 AI 讨论时特意确认了语义这是个人宠物管理工具删除一只宠物通常意味着“我不想再管这只宠物了”那历史提醒和事件留着没有意义级联删除是合理选择。但如果你做的是宠物医院系统删除宠物档案时必须保留诊疗记录那就要改成Restrict。这个决策没有标准答案完全取决于业务语义。第二个关键点是intervalDays设为Int?也就是可空。空值代表“一次性提醒”比如某个特殊的就诊提醒只提醒一次不需要循环有值代表“循环提醒”比如驱虫每 90 天一次。这样一张表同时承载两类提醒不需要另建一张一次性提醒表。第三个点很容易被忽略dueDate存的是“计算后的具体日期”而不是“每隔 90 天提醒一次”这种规则表达式。原因很实际具体日期可以按天查询、可以做聚合、可以显示在日历上。规则表达式在查询“今天有哪些事要做”时需要现算数据库也没法索引。空间换成本这笔账很划算。3.3 让 AI 解释每一处设计的“为什么”我建完模型后做了一件很关键的事没有直接“下一步”而是让 Claude Code 逐段解释自己的设计。我当时的指令是“逐字段说明每个字段为什么必填/可空外键为什么选这个级联策略如果用户完成了一条循环提醒应该更新哪些字段如果今天是发的通知日但用户没处理这个模型怎么表达”这一步的价值是双重的。一方面我作为项目负责人必须理解每处设计才能做后续开发另一方面让 AI 解释的过程也是验证逻辑一致性的过程。如果它解释得含糊或自相矛盾说明模型本身有问题趁早改比日后返工便宜太多。4. 从 API 到页面先打通数据链路再打磨 UI 细节数据模型定稿、数据库迁移完成之后就进入了全项目迭代最频繁的阶段写接口、做页面。这个阶段我踩过的最大坑是顺序问题。4.1 为什么顺序是 API 先于页面直觉上很多人会先做页面因为页面看得见摸得着成就感强。但从工程效率来看先做 API 更稳。页面出问题你一眼就能看到而且报错信息通常很直观API 出问题比如字段名不对、类型不匹配往往是页面白屏或接口报错时才暴露排查链路更长。所以我让 Claude Code 先完成一组基于数据模型的增删改查接口再用类似 curl 的命令或接口测试工具验证一遍确认数据通路是完整的然后才开始写页面。这样就算页面写歪了至少能确定问题在前端而不是后端。4.2 一轮具体的对话闭环宠物列表接口怎么落地的以“宠物列表接口”为例我向 Claude Code 描述的需求是“提供一个 GET 接口返回所有宠物列表按创建时间倒序每条宠物数据里包含它的提醒数量统计和一个最近一次健康事件摘要。”这段描述里有排序规则、有统计信息、有嵌套摘要比只说“给我一个宠物列表”要精确得多。它生成的代码风格大概是import { prisma } from /lib/prisma; import { NextResponse } from next/server; export async function GET() { const pets await prisma.pet.findMany({ orderBy: { createdAt: desc }, include: { _count: { select: { reminders: true, events: true } }, events: { orderBy: { recordedAt: desc }, take: 1 }, }, }); return NextResponse.json(pets); }代码本身不复杂但注意它通过include和_count一次性把统计信息和最新事件拉出来了避免了前端做多次请求。这种优化思维不是靠我描述出来的而是 AI 基于常见实践自动选择的。原因在于我的需求描述里明确说“每条宠物数据里包含”它就理解了数据结构应该怎么组装。接口写完后我做的验证是启动本地服务用一条 curl 命令打一下接口确认 JSON 字段和预想一致。这一步确认了页面开发时就不用反复猜测数据结构。4.3 UI 从毛坯到精装三轮迭代的具体过程我让 Claude Code 做页面不是一蹴而就而是明确分了三个阶段第一阶段是“毛坯版”。目标是所有页面挂上真实接口数据不做任何视觉设计。列表就是原生列表表单就是最朴素的输入框。这一轮的意义是验证数据绑定是否正确路由跳转是否通畅。第二阶段是“功能型精装”。这个阶段才考虑布局、卡片、状态。比如宠物列表改成卡片网格仪表盘加上“今日待办”“最近记录”两个区块表单加上必填校验。Tailwind 这类原子化 CSS 在这里帮了大忙AI 生成样式会很顺手。第三阶段是“细节型打磨”。空状态、加载状态、错误提示、日期选择控件、按钮的禁用态这些看似不起眼的地方恰恰区分了一个 App 是“能用的 Demo”还是“拿得出手的工具”。我一般会专门抽一个会话只处理这些边界细节。三轮迭代下来整个 App 的质感会有一个明显的跳跃。前两轮 AI 的产出大概是 70 分最后一轮人工参与的比例会提升到 40% 左右因为“品质感”这件事AI 目前还没有足够好的审美判断力。4.4 AI 代码里最容易出现的三类幻觉以及我的排查方式和 Claude Code 合作几周后我总结了它最容易出现的三类“一本正经的胡说八道”第一类是编造未安装的依赖。代码里 import 了一个看起来很合理的库但package.json里根本没有。排查方式很简单让它报错日志原样贴回去AI 会自己发现问题并补装。第二类是编造不存在的 API 签名。比如某个框架的 props、某个库的配置项AI 记忆出错导致“形似而神不似”。这个靠语法检查很难发现最好的办法是在审查 diff 时多问一句“这个参数在官方文档里确实存在吗”或者直接把关键报错贴回去。第三类是冗余封装。明明 Prisma 已经生成了数据库访问层它又自己包了一层“工具函数”美其名曰可维护性实则增加跳转成本。对这种代码我会明确要求“删除这一层封装直接调用 Prisma”。这里有个核心心态把 AI 当成一个特别聪明、偶尔会自信地犯错的结对实习生。它写出来的代码必须经过 review就像你 review 新同事的代码一样不吹不黑有问题就指出来让它改。5. 循环提醒模块这个业务最绕的逻辑怎么写才不翻车宠物生命周期管理 App 最核心的业务逻辑不是增删改查而是“循环提醒”。这条逻辑不复杂但边界条件多一不小心就翻车。5.1 下一次到期日怎么算循环提醒的存储方式之前已经说了一张提醒表记录上一次完成时间和间隔天数。那“下一次到期日”就是两个字段相加。我用 Claude Code 实现了一个独立函数export function getNextDueDate(lastCompletedAt: Date, intervalDays: number): Date { const next new Date(lastCompletedAt); next.setDate(next.getDate() intervalDays); return next; } export function isDue(reminder: { dueDate: Date; completed: boolean }): boolean { if (reminder.completed) return false; const today new Date(); today.setHours(0, 0, 0, 0); return reminder.dueDate today; }isDue这个函数负责判断“今天要不要做这件事”。注意它的逻辑已完成的不算待办到期时间早于或等于今天零点就算待办。这里有个细节new Date()里包含时分秒如果不归零到当天 0 点会出现“昨天到期但其实今天才看到”的边界瑕疵。这类细节我一般会主动问 AI“会不会有日期边界问题”让它自查。5.2 种子数据模拟真实时间线提醒逻辑写完之后没法立刻验证效果因为数据库是空的。这时候种子数据脚本的价值就体现出来了。我让 Claude Code 写了一个 seed 脚本造了 3 只虚构宠物并生成了一组分散在过去、今天、未来的提醒记录。宠物 A疫苗下次到期日就在今天驱虫 20 天后到期已完成一次年度体检。 宠物 B疫苗 30 天后到期驱虫已在 5 天前到期未完成。 宠物 C一只新领养的小猫所有提醒都是未来时间。这三组数据覆盖了“今日待办”、“已过期未处理”、“未来计划”三种典型状态。跑完 seed 脚本再打开仪表盘立刻能看出界面是否完整反映了业务状态。种子数据不只是给开发阶段用的它还是你和 AI 沟通需求时的“共享语境”。你描述“宠物 A 的疫苗今天到期但页面没显示”AI 立刻能定位问题因为它知道宠物 A 是个虚构数据而不是真实用户信息。5.3 今日待办状态机和“完成一条提醒”的连锁反应“完成一条循环提醒”这件事看似只是把一个字段改成 true但实际牵涉三个更新先记录本次完成时间再算出下一次到期日最后把 completed 状态复位。所以我专门和 Claude Code 讨论了这个动作的语义最终方案是提供一个专门的完成接口而不是让前端直接拿通用更新接口改字段。export async function completeReminder(id: string) { const reminder await prisma.reminder.findUnique({ where: { id } }); if (!reminder) { throw new Error(提醒不存在); } const now new Date(); const nextDueDate reminder.intervalDays ? getNextDueDate(now, reminder.intervalDays) : null; return prisma.reminder.update({ where: { id }, data: { completed: true, lastCompletedAt: now, dueDate: nextDueDate ?? reminder.dueDate, ...(nextDueDate null { intervalDays: null }), }, }); }为什么用专门接口而不是通用 PATCH因为“完成”是业务动作不是字段覆盖。通用 PATCH 允许前端传任意字段万一漏传lastCompletedAt下次到期日就算不出来数据就脏了。让服务端统一处理这个业务逻辑前端只需要告诉它“完成这条提醒”剩下的计算全部由后端负责。这样设计之后前端“今日待办”逻辑也变得很简单加载所有dueDate today !completed的提醒点击完成按钮就调这个接口接口返回新数据后刷新列表一条提醒自然地从待办区消失滚动到下一轮。整个过程不需要前端做任何日期计算。6. 运行验证与人工走查把 AI 交付的东西当成新同事的代码来审功能开发完成不是项目的终点。跑测试、走查边界、修构建错误这一步我把它叫“交付前的最后一百米”。少了这一步前面所有的顺利都可能被上线时的低级错误毁掉。6.1 让 AI 自己写单元测试Claude Code 这类工具其实特别适合写单元测试因为测试目标清晰、输入输出明确。我让它为提醒计算逻辑写了一批测试覆盖三种典型场景间隔天数累加、跨月跨年、2 月 29 日的边界。大致长这样import { describe, expect, it } from vitest; import { getNextDueDate, isDue } from /lib/reminder; describe(getNextDueDate, () { it(应该在起始日期基础上累加间隔天数, () { const start new Date(2025-01-01); const next getNextDueDate(start, 90); expect(next.toISOString().slice(0, 10)).toBe(2025-04-01); }); it(跨年计算仍然正确, () { const start new Date(2025-12-15); const next getNextDueDate(start, 30); expect(next.toISOString().slice(0, 10)).toBe(2026-01-14); }); });让 AI 写测试有一个额外好处它会重新审视自己的业务代码经常能发现隐藏在逻辑里的不一致。有一次它写完测试后主动提出“现有一个函数没有处理一次性提醒的情况我应该补一个判断分支。”这种自我纠错能力在纯人工开发里不会那么频繁出现。6.2 迁移流程和构建错误处理数据库模型改过几轮之后记得执行迁移命令把 Schema 同步到数据库。这里最容易犯的错是改了模型忘了迁移运行时报“表不存在”。我习惯让 Claude Code 在每次改完模型后自动补上迁移相关命令别等手动发现。构建检查是另一道防线。开发环境能跑不代表生产构建能过。我一般会要求 AI 运行npm run build然后让它自己把报错修复到通过为止。这一步能过滤掉大量类型错误、未使用变量、客户端服务端组件混用问题。6.3 我的走查清单在宣布这个小应用“可用”之前我会拿着下面这张清单手动过一遍检查项具体内容空状态没有宠物/没有提醒/没有健康事件时页面是否正常显示而非报错或空白日期边界跨月、跨年、2 月 29 日、到期日恰好在今天 0 点待办是否正常出现与消失级联行为删除宠物后提醒和事件是否按预期被清理页面统计数字是否更新URL 直接访问直接输入详情页 URL 访问不存在的 ID是否有合理的 404 或错误提示表单校验必填字段为空、日期格式不对、负数体重输入是否被挡住并给出提示重复点击点击“完成”按钮多次是否产生重复提交或字段错乱这份清单不是我发明的是前几次用 AI 开发时踩了坑才总结出来的。每一条背后都对应一次真实的翻车经历。6.4 对 AI 编程工具边界的一点真实感受跑完测试、走查完清单、构建通过这个宠物生命周期管理 App 的 MVP 就算完成了。但从这次项目里我体会最深的不是 AI 帮我省了多少时间而是人类工程师的职责正在悄悄变化。它擅长结构化产出从数据模型到接口到页面只要有清晰的输入它能在几分钟内给出大量可用的代码。但它不擅长品味判断、不擅长理解业务潜台词、也不擅长替你做取舍。比如“这个 App 给人的感觉应该偏温暖还是偏专业”“名单里要不要默认展示某只刚去世的宠物”“删除按钮应该放显眼位置还是收进二级菜单”这些问题的答案在代码里找不到只能靠业务判断。我渐渐建立起一套自己的工作规矩每次和它对话前先花几分钟把需求写清楚包括背景、修改范围、验收标准每次改动限制在一个小目标内不让会话无限膨胀所有复杂的业务逻辑都要求它附带测试和解释。这套规矩让我从“AI 用得手忙脚乱”变成“AI 用得得心应手”。最后分享一个我个人觉得最有用的习惯开始一个新功能前先让 Claude Code 写一段“实现方案说明”而不是直接让它写代码。这段说明里必须包含它准备改哪些文件、为什么这么改、有没有需要我确认的取舍点。我把这当作一种低成本的评审机制——等它把思路写出来我一眼就能看出哪里不对比等它写完几百行代码再审要轻松太多。用这个习惯我在这个宠物项目的后半段几乎没遇到过方向性返工。希望这篇记录能给你一些参考也欢迎你在自己的项目里试试这套协作方式。