← Blog

花了 6 个月我到底做了个什么

一篇关于 AI 项目收尾、落地与个人方法论的项目复盘。

ModelCraft

一个人的全链路:8个月,我怎么从调研走到上线

引子

去年十月,随着AI coding的冲击, 我们的低代码项目逐步从中心转移, 渐渐停止更新。 作为从事了5年数据模型设计的我,也渐渐开始转换方向。

不管是处于或多或少,这儿那儿的原因。 在我心中算是只做了一个61分的答卷,刚刚及格一点。其实就是这里我们没做好。

我在这个领域做了五年,这五年里,有一件事一直压在心里:我总觉得这件事可以做得更好。

不是说我不知道问题, 而是我清清楚楚的知道问题在哪,知道踩了哪些坑,有哪些痛点,哪些设计不好。难以从中抽离, 对于团队来说,很难做到灵活的调整方向,也不可能做一个事情持续打磨好了再上线。

所以我心中一直埋藏这一个重写数据模型的种子。

还有一个更具体的问题,埋在心里更久——

“你们的 DSL 文档我看了,但还是不知道这个字段支持哪些查询操作符。”

这是一张两年前的工单。处理完之后随手存了下来,也不知道为什么。后来每次遇到类似的工单,脑子里都会有个声音:为什么写了文档,用户还是不会用? 这个问题我没有答案,但它一直在。

直到我读《凤凰架构》,翻到 GraphQL 那一章。

那根线突然接上了:GraphQL 的 Introspection,让协议本身就能解释自己。 不需要文档,不需要训练,AI 查一次 Schema,就能知道这个字段支持哪些查询操作符。

那个压了两年的问题,答案就在这里。

但知道方向,还不够。上一次失败,除了思路没想通,还有一个原因:产品设计、前端、测试,一个人同时扛,效率撑不住。

这一次,AI coding 开始真的能用了。

两件事同时到位——清晰的入口,和够用的效率。这才是这一次没有再退出来的原因。

八个月之后,我把它做完了。这篇文章想做一件事——把这八个月里「产品调研 → 核心设计 → 后端架构 → 系统设计 → 前端 → UI」这一整条链路,完整地讲出来。不只是「我做了什么」,而是「我在每一层是怎么想的,选了什么,为什么,踩了什么坑」。

一个人能不能搞定全链路?

这是我当时最大的问题。也是这篇文章想回答的问题。


1. 产品调研:我在和谁竞争,差距在哪里

动手之前,我花了将近一个月深度使用了三个产品:Supabase、Prisma、PostgREST。

不是走马观花地看 Feature List,是真的把它们接进项目里用,遇到问题查文档,查不到就翻 Issue,翻完 Issue 再看源码。

用完之后,我得出一个让我有点不舒服的结论:

我们的差距,不在功能,在协议。

Supabase 的查询接口、Prisma 的 Schema DSL、PostgREST 的 OpenAPI,这些东西不只是「设计得好」——它们是被大模型训练过无数次的数据。你让 GPT 写一段 Prisma 查询,它能写出来,因为 GitHub 上有几十万个 Prisma 的示例。你让它写我们自己内部数据模型的 SDK,它大概率会胡说,因为它根本没见过。

这是一道几乎无法靠追赶来弥补的鸿沟。

但问题不只是「知名度」。我在用这些产品的过程中,注意到它们有一个共同特质:强约束。Prisma 的 Schema 是强类型的,非法操作在 codegen 阶段就报错;Supabase 的接口有完整的 OpenAPI 描述,每一个字段、每一个过滤条件都有明确的边界定义。

这种强约束不只是为了开发体验——它是让 AI 能够「自我学习」这套系统的前提。结构化的、有边界的协议,对 AI 天然友好。

反观我们自己的 SDK,设计上缺少这种整体性。工整性和严谨性差一点——这不是苛责,而是 SDK 这种东西本来就难做。SDK 有一个别的产品没有的特殊困难:代码留在客户那里

API 挂了,你重启服务;SDK 的 bug,你得说服客户升级。而客户不一定会升级,他们更可能是绕过去——写一段奇怪的兼容代码,然后把这个绕法口口相传给新人。久而久之,你的 bug 就变成了「特性」。

我们之前有一段逻辑:任何 24 位字符串,自动转换成 MongoDB 的 ObjectId;否则当普通字符串处理。这个逻辑最初可能是某个边界情况下的 workaround,后来没人愿意动它——改了怕影响已有的客户,不改又说不清楚为什么要这样。于是它就活了下来。每一个新客户接入,都要经历一次「这是什么鬼」的疑惑,然后在某个内部文档里看到一行神秘的注释,才能理解。

这件事给我的教训是:协议的严谨性,是要在最开始就定下来的。 后补是补不上的。

但最让我刻骨铭心的,不是这种边角料的 bug,而是两次更大的教训。

第一次:过早引入复杂关联。

我参与过的低代码平台很早就引入了数据与部门之间的关联——而且是一条数据可以挂多个部门的多对多关系。这个需求本身是真实的,某些场景下确实需要。但它被引入的时机太早了,协议还没有稳固,就开始承载这种复杂性。

结果是什么?标准协议开始变形。原本清晰的查询逻辑,为了处理「这条数据属于哪些部门」,开始长出各种特殊分支。一个标准路径,悄悄变成了三个路径,然后是五个。后来接手的人看到这段代码,第一反应不是「我来改」,而是「我先搞清楚为什么这里有五个分支」。

协议一旦开始为特殊逻辑服务,就很难再变回普通逻辑了。

第二次:OR 查询逻辑的缺失。

这个更惨。我参与过的低代码平台,数据引擎的查询协议在设计之初没有考虑 OR 逻辑——所有条件默认 AND。

单独看,这好像是个小问题。但数据引擎是低代码平台的下限,存储始终是程序的核心。用户在前端拖了一个列表组件,想筛选「状态是已完成,或者负责人是自己」——这是最普通不过的需求,但底层协议不支持 OR,你能怎么办?只能绕。绕法五花八门,最后每个绕法都是一个新的隐患。

后来终于下决心升级协议,加入 OR 支持——这个阵痛持续了将近一年。不是因为技术难,而是因为已经有太多东西建在旧协议上了。每改一处,就要排查十处。

一年。为了一个本来在设计阶段应该考虑到的逻辑。

这背后有一个更深的问题:那段时间,重心放在了前端编辑器、流程审批、模板安装上,没有把「重新设计数据引擎协议」放到最高优先级。 这些功能都很重要,用户也确实在要,但它们是支线任务。数据引擎协议,才是主线。

任何低代码平台,数据引擎都是它的下限。下限不稳,上层建得再高,也是在沙滩上盖楼。

我后来总结出一条规矩,送给所有做基础设施的人:你必须清楚什么是你的主线任务。不是用户最响亮的那个需求,不是竞品最新发布的那个功能——是你的系统如果在这里出了问题,一切都会停摆的那个地方。那里,才是你的主线。

带着这些教训,我开始思考协议的边界问题。

调研完 Supabase、Prisma、PostgREST,我还注意到一件事:它们都很克制。Prisma 不做运行时,PostgREST 不做权限管理界面,Supabase 把边界划在「开箱即用的 Firebase 替代品」上,出了这个圈子就不跟你聊。

这种克制不是偷懒,是生存本能

做协议、做平台,最大的陷阱不是功能不够,是边界不清。这个客户要一个字段加个自定义校验,那个客户要支持一种新的操作符,每一个需求单独看都合理,但如果你都答应,最终做出来的东西就是「四不像」——什么都有,但没有一件事是它该做的。

我在这个领域见过太多这样的产品。一开始定位清晰,后来被需求推着走,边界一退再退,最后连自己的团队都说不清楚「这个产品到底是给谁用的」。

所以 Modelcraft 从调研阶段就给自己定了一条规矩:协议要强约束,边界要守住,不因为某个客户的需求就突破设计边界。

大而全的协议是不存在的。你能做的,是在自己守得住的范围内,把它做到极致。

下一个问题是:用什么协议,才能守住这个边界?


2. 核心设计:一个人怎么弯道超车

调研完竞品,我面对一个很现实的问题。

Prisma 的强类型 Schema、严格的查询约束、完善的文档——这些东西我都想要。但 Prisma 是一个团队做的,背后有完整的 SDK 设计体系、有专职的文档团队、有几年的社区积累。

我只有一个人。

正面竞争是没有意义的。一个人写的 SDK,再努力也写不过一个团队;一个人维护的文档,再认真也会有死角。我需要找到一条不同的路——不是做得比他们更多,而是找到一个他们用了很多资源才解决、而我可以用更少资源解决得更好的问题。

这就是弯道超车的本质。

我当时在读《凤凰架构》,读到 GraphQL 那一章,脑子里有根线突然接上了。

GraphQL 有几个特质,放在一起看,非常特别:

  • 强类型 Schema:每个字段、每个查询参数都有类型约束,非法操作在协议层就会被拒绝
  • Introspection:任何客户端都可以查询「这个接口支持哪些字段、哪些操作」,不需要额外的文档
  • 结构化错误:报错不是一个模糊的字符串,而是有结构的、可解析的信息

我盯着这三条,忽然反应过来。

我们整个行业这两年都在讨论:如何让接口 AI 化?如何写出让 AI 能读懂的接口文档?如何在调用出错时给 AI 明确的反馈?这三个问题,其实 GraphQL 早就回答了——强类型是 AI 的护栏,Introspection 是 AI 的地图,结构化错误是 AI 的纠错机制。

GraphQL 不是为 AI 设计的,但它天然是 AI 友好的。

更关键的是:这条路 Prisma 没有走。Prisma 选择的是「用 SDK 封装复杂性」——它把强约束用代码生成来实现,好处是开发体验极好,代价是你必须用 Prisma 的方式、Prisma 的生态。一旦出了 Prisma 的范围,就没有这些保障了。

我的思路反过来:不用 SDK,直接暴露 GraphQL。 不需要客户安装任何东西,不需要代码生成,任何能发 HTTP 请求的客户端都能用——包括 AI。

这就是弯道超车的地方:Prisma 用一个大型 SDK 解决的问题,我用 GraphQL 的协议本身来解决。我不需要维护 SDK,不需要写文档,Schema 本身就是文档,Introspection 本身就是自我描述。

一个人对抗一个团队,唯一的办法是让协议替你干活。

决定了方向,下一个问题是:GraphQL 解决了「AI 怎么理解这套系统」,但另一个更基础的问题还没有答案——这套系统的数据,怎么和数据库对应起来?怎么做权限?怎么做多租户?

这就到了后端架构要解决的问题。


3. 后端架构:一个人做 DDD,以及抄 PostgreSQL

后端架构我做了四个核心决定。每一个背后都有一段故事。

第一个决定:DDD 四层架构。

DDD 这件事,我已经实践过了,博客也看了很多。它能带来什么我是清楚的:单向依赖、防腐层、完善的单元测试、各模块最大程度解耦。

但凡在团队里推过 DDD 的人都知道,这件事最难的不是架构设计本身,而是让团队遵守。分层规则、依赖方向、防腐层的边界——这些东西写在文档里是清晰的,但落到每个人每天写的代码里,会慢慢腐化。一个人图方便跨层调用了,另一个人觉得「就这一次没关系」,慢慢地,架构图和代码就对不上了。

一人项目直接解决了这个问题。

不需要 Code Review 来守纪律,不需要 ADR 来说服别人,不需要在周会上解释为什么不能这样写。就我一个人,我说什么是对的,什么就是对的。这是一人项目少有的几个优势之一,我把它用足了。

第二个决定:Schema 驱动,代码全生成。

前端和后端之间,我一直推崇一件事:用 Schema 生成 interface 层和 client 层,双向都生成,中间不留任何手写的胶水代码。

这样做的结果是:前后端好像天然是一体的。后端改了一个字段,前端 codegen 一跑,类型错误立刻暴露,不会等到联调才发现。接口的分歧,在编译期就消灭了,而不是留到运行时。

后端我用 gqlgen——GraphQL Schema 生成 Go 的 interface,resolver 必须实现这个 interface,否则编译不过。同时用 sqlc——直接写 SQL,反向生成 Go 代码。

sqlc 这个选择有点反常识。大多数项目会选 ORM,因为 ORM 屏蔽了 SQL 的复杂性,开发更快。但我做这个选择,有一个很具体的原因:AI 对 ORM 框架的理解有认知差异。

框架版本不同,一些小特性的行为不一样;新版本的用法,训练数据里可能没有。AI 生成的 ORM 代码,你不能完全相信它——你得自己读,自己验证,有时候还得帮它纠错。

但 SQL 不一样。SQL 是标准的,AI 见过无数遍。我把复杂的查询逻辑直接写在 .sql 文件里,sqlc 负责生成类型安全的 Go 代码,AI 协助我写 SQL——这个分工非常顺畅,我从来没有为「AI 写错了 ORM 语法」这件事烦恼过。

第三个决定:多租户设计。

这个决定对我来说是直觉——做了这么多年云计算,多租户是刻在骨子里的东西。而且 Modelcraft 本身就是一个 SaaS 平台,Org / Project 两层隔离是自然而然的结果。

没有太多纠结,就是做了。

第四个决定:RLS(行级安全)。

这个是我一开始觉得最难的东西。同一张表,不同用户只能看到属于自己的数据行——听起来简单,实现起来要考虑的边界情况非常多。

我最早想的方案是规则引擎。类似 Firebase 的 Security Rules——用户自己写 policy,引擎在运行时对每条查询做求值,决定这一行能不能返回。这个方案很灵活,表达能力强,Firebase 用它支撑了非常复杂的权限场景。

但灵活是有代价的。规则引擎意味着我要自己定义一套 policy 语法,要写解析器,要处理规则之间的优先级和冲突,要让用户学会写这套语法——每一项单独看都不难,但加在一起,就是一个新的复杂度层。

然后我去看 Supabase 怎么做的。

Supabase 的答案出乎意料地简单:直接用 PostgreSQL 原生的 Row Level Security。 不造新轮子,不发明新语法,用数据库本身几十年积累下来的能力。

我当时的第一反应是:对,就应该这样。

PostgreSQL 的 RLS 经过了十几年的打磨,边界案例都被处理过了,文档完善,社区里有大量的讨论和实践。我没有理由发明一套新的。我只需要把它的设计思路搬到 Modelcraft 的上下文里,适配 MySQL 的约束。

有时候,最好的设计决策不是创新,是找到一个已经被验证过的答案,然后老老实实地用它


4. 系统设计:B2B2C 的链路,和一根贯穿始终的日志

系统设计这层,我做了三个决定,背后的逻辑都和同一件事有关:我服务的不只是一种用户。

Modelcraft 本质上是一个 B2B2C 的产品。我面向的是开发者(B),但开发者背后还有他们自己的客户(C)。这两层用户的需求不一样,对 SLA 的要求也不一样——开发者可以接受偶尔出错、自己排查;但开发者的客户不行,他们感知到的任何异常,都会第一时间反馈给开发者,开发者再来找我。

所以系统里有很多设计,本质上都是在处理这个链路:让开发者先灰度,先发现问题,再让真正的终端用户进来。

Gateway:最大化用开源,提前埋私有化的根。

Gateway 我直接选了 APISIX。不自己造,不魔改,直接用成熟的开源方案——这是一人项目的生存原则:把精力留给只有我能做的事,能用开源替代的绝对不自己写。

APISIX 解决了认证、路由、限流这些基础问题,我在上面做了 Developer 和 EndUser 两套链路的分发——开发者走管理侧,终端用户走数据侧,两条链路的鉴权逻辑、错误返回、日志格式都是分开处理的。

有一个细节:我在设计 Gateway 层的时候,就提前为私有化部署埋下了接口。这是我做了几年云计算之后养成的直觉——SaaS 和私有化之间的差异,往往不是功能差异,而是部署边界和配置入口的差异。如果等到真的有客户要私有化再来改,代价会很大。提前埋好,将来只是换一套配置。

CLI:一个从真实对话里长出来的产品。

CLI 不在我最初的规划里。

真正推动我做 CLI 的,是和几个开发者客户的对话。他们的需求有一个共同特征:想管理数据、统计数据,但这个需求太轻了,不值得专门做一个管理页面。

他们本来的方式是:自己写一段 Python 或者 Shell,拼几个 API 调用,跑一下,看结果。这是开发者天然的工作方式——胶水语言 + 命令行组合。

我意识到,如果我提供一个标准的 CLI,这个场景就被完整覆盖了:低频操作不需要 UI,开发者用自己熟悉的方式组合命令,而且——CLI 天然对 AI 友好

你可以直接告诉 AI:「用我的 mc 命令,token 是这个,帮我查一下 orders 表里最近一周的数据。」AI 自己会查 help,自己会组合参数,自己会解析输出。这个体验,比任何 UI 都顺畅。

CLI 是附加产品,但它最终成了 Modelcraft 最 AI 友好的入口。

可观测性:所有模块跑通之后,真正难的才开始。

在 Vibe Coding 的节奏下,把所有模块联调跑通,说实话没有想象中难——AI 大幅降低了模块间胶水代码的成本,跑通这件事本身不是瓶颈。

真正难的,是跑通之后:出问题了,你怎么知道问题在哪?

一个请求从 CLI 发出,经过 Gateway,进后端,查数据库,返回结果——这条链路上任何一层出错,如果日志不标准,你就得靠猜。我在这个阶段吃了一些苦头:同样是一条错误日志,有的带着完整的 RequestID 和调用链,有的只有一行「something went wrong」。排查的时候,前者五分钟定位,后者可能要半小时。

所以我把可观测性单独当成一个系统设计问题来处理:

  • 所有服务的日志格式统一,结构化输出,方便机器解析
  • 每个请求有唯一的 RequestID,贯穿整条链路
  • 错误分层:哪层出的错,就在哪层记录,不往上层透传原始错误

这件事不性感,不是什么新技术,但它是系统能不能被人用的基础。一个可观测的系统,才是一个真正能运行的系统。


5. 前端设计:一个不懂前端的人,怎么用 AI 写前端

我是完全不懂前端的人。

不是「懂一点但不精」,是真的不懂——CSS 怎么布局我说不清楚,React 的 re-render 机制我只有模糊的印象,组件库怎么选我没有判断标准。

所以前端这层,我做的第一件事,是承认这件事,然后想清楚:在「完全不懂」的前提下,怎么把事情做对?

技术选型:简单的就是最好的。

对我来说,技术选型的原则只有一条:选最简单的、AI 最熟悉的。

Next.js 就这样进入了我的视野。它有足够大的社区,AI 训练数据里有无数个 Next.js 的项目,出了问题基本上一问就有答案。shadcn/ui 同理——组件是复制进来的,不是装进来的,AI 能直接看到组件代码,不会因为版本差异产生理解偏差。

前端的规范和标准化,我让 AI 帮我制定了一套——代码风格、组件命名、目录结构、设计 token。我不需要自己懂这些,我只需要让规范是一致的,然后让 AI 在这个一致的上下文里工作。

功能边界:难的不是做加法,是决定不做什么。

前端功能的最大挑战,不是「这个功能怎么实现」,而是「这个功能要不要做」。

AI 写前端的速度很快,快到会产生一种错觉:「反正也不费什么,加上去吧。」这个念头非常危险。每一个「反正也不费什么」的功能,都会带来维护成本、交互复杂度、和用户的认知负担。

我在前端砍掉了非常多东西——砍掉了复杂的数据可视化,砍掉了自定义仪表盘,砍掉了很多「用户可能会想要」的功能。留下来的,只有「用户完成核心任务必须有」的部分。

这是产品调研那章「守住边界」的同一条原则,在前端的重演。

AI 不能盲写:你不能一直保持「不懂」的状态。

这是我整个前端开发过程里,最重要的一个认知转变。

很多人理解 Vibe Coding 的方式是:我不需要懂,我只需要告诉 AI 我要什么,它帮我写。这个理解是错的——或者说,它只在最简单的场景下成立。

真实的情况是:你不能一直保持不懂的状态,否则你连问题在哪都说不清楚。

我给自己定了三条最低限度的前端能力要求:

第一,基本的调试能力。如果你要调整一个组件,你得能告诉 AI「这个组件在哪」。具体的方式是:打开浏览器 DevTools,右键检查,拿到这个组件的 HTML 结构特征——类名、层级、唯一的属性。这就是组件的「指纹」。把这个指纹告诉 AI,它才能精确定位,而不是瞎猜。

第二,URL 到代码的映射。你不需要知道组件怎么写,但你要知道:你在浏览器里看到的这个页面,对应的是哪个路由,代码在哪个文件夹里。这是最低的定位能力,没有它,你和 AI 的对话会永远停留在「那个页面上有个按钮」这种模糊描述里。

第三,基本的架构知识。这个我有一个亲身经历——某次迭代里,我引入了 BFF 层。BFF 是什么?我当时并不清楚。我和 AI 探讨了很久:BFF 到底解决什么问题?它和直接调后端有什么区别?为什么前端需要一个专属的后端?

这个讨论花了我不少时间,但它是值得的。因为只有真正搞清楚 BFF 是什么,我才能在后续的开发里做出正确的判断——什么逻辑放 BFF,什么逻辑放前端,什么逻辑应该推到后端去。架构的认知,是 AI 没办法替你建立的。

但我想说的不只是这三条能力本身,而是一个更底层的工作方式。

前端有一个天然的优势:快速反馈。你改了一行 CSS,浏览器立刻告诉你对不对;你调了一个组件,保存之后马上看到结果。这种即时反馈,让「先做出来,再搞懂」成为一种可行的学习路径。

很多时候,当我真的不会某件事,我会先让 AI 硬怼出来——不管原理,先跑通,先看到效果。这在前端是完全可行的,因为反馈回路很短,跑不通马上就知道。

但关键在下一步:做出来之后,我会让 AI 帮我梳理「这是怎么做到的」。

不是忽略它,不是「能用就行」,而是专门停下来,让 AI 解释这段代码的逻辑,解释它做了什么决定,为什么这样设计。这个过程有时候只需要五分钟,但它让我从「这个功能跑通了」变成「我真的理解这个功能」。

这个习惯,让我在整个前端开发过程里,保持了一种持续的学习状态——不是被动地让 AI 写,而是主动地把 AI 当成老师。

我认为,在 AI Coding 时代,快速学习陌生领域的能力,比任何具体的技术技能都重要。 技术可以让 AI 帮你写,但理解力只能自己建立。有了理解力,你才能在下一次遇到类似问题的时候,做出正确的判断——而不是永远依赖 AI 从零开始。

Vibe Coding 的真相是:AI 负责写,你负责懂。 你懂得越多,AI 写得越准;你越是甩手不管,AI 越容易把你带进沟里。


6. UI 设计:从「不知道该做成什么样子」到品牌体系

UI 设计是我最没有底气的一层。

不是「不懂设计工具」,是更根本的——我不知道好看的界面是怎么来的。 审美对我来说是一个黑盒,我能感觉到某些东西好看,但说不清楚为什么,也不知道怎么复现。

所以我做了一个最务实的决定:先不管 UI,飞速走通核心功能。

这个决定省了我很多心理负担。早期的界面丑没关系,能用就行——反正先验证逻辑对不对,UI 是最后一层,可以补。

但「补」这件事,最终还是要面对的。

第一步:建立品牌形象。

我用了 impeccable 这个 AI 设计技能来分析和优化界面。它做的第一件事,不是帮我调颜色,而是逼我回答一个问题:这个产品想传递什么感觉?

Modelcraft 是一个数据平台,面向开发者。我想要的感觉是:克制、精准、有技术质感,但不冷漠。不是那种花里胡哨的 SaaS 风,也不是极简到没有个性的工具风。

有了这个方向,颜色和字体就有了判断标准。最终定下来的色盘是深色主题——#0E0E11 的近黑底色,#4F46E5 的靛蓝作为主色调,配上 Inter、Space Grotesk、Fira Code 三套字体,覆盖界面文字、标题、代码三个场景。

Logo 的灵感来自几何图形——两个三角形交叠构成的六芒星,内嵌 Schema Graph 和 Runtime Layer 的层次关系。不是为了好看而设计,而是让 Logo 本身承载产品的架构隐喻。

品牌 Tagline 也在这个过程里定下来:Where models become APIs.

一句话说清楚产品是什么。

第二步:锁死 Design Token,写进 Lint 规则。

品牌形象定完,我做的第一件事不是去美化界面,而是把所有的 Design Token——颜色、间距、字体权重——全部写进 ESLint 规则里。

原因很简单:AI 写代码的时候,如果没有约束,它会用任何它觉得合理的颜色和间距。text-gray-600font-boldp-3——这些都是合理的,但它们不是我定义的设计语言。

有了 Lint 规则,AI 一旦偏离设计体系,编译就会报错。不需要我人工 review 每一行样式代码,规则替我守住了一致性。

第三步:提取公共组件,消灭设计漂移。

在做完大部分页面之后,我做了一次全面的组件审计,发现了一个典型问题:Header、Sidebar、各种卡片的实现,在不同页面里存在细微的差异——颜色深浅差一点,间距多几像素,圆角大小不一致。

这就是「设计漂移」——没有统一的组件,每次 AI 实现同一个 UI 模式,都会有细微的偏差,积累下来,整个产品就会有一种说不清楚哪里不对劲的不统一感。

解法是把所有重复的实现提取为公共组件,每个组件只有一个实现,所有页面共用。改一处,处处生效。

第四步:用 AI 重新生成所有图片资产。

最后,我把产品里所有的图片——图标、插图、品牌图——用 Lovart 重新生成了一版,统一风格。

下面这张是最终的品牌概念图:

[品牌 Kit 图 — 插入 brandkit 图片]

从「不知道该做成什么样子」,到有一套完整的设计语言——回头看,这个过程对我来说并不神秘。

我没有审美细胞,我也不打算培养审美细胞。我只是把设计当成了一个工程问题来解决:定义规则,用工具执行规则,用系统保证一致性。

对于没有审美细胞的人来说,把设计做成工程化,是最容易理解的事情。


7. 写在最后:一个人能不能搞定全链路?

这是我八个月前最大的问题。

现在我有答案了。

能。但不是我想象中的那种「能」。

我以为「搞定全链路」的感觉,是每一层都做得很好——产品调研很扎实,架构设计很优雅,前端很漂亮,UI 很精致。像一个全能型选手,每个维度都在水准线以上。

实际上不是这样的。

实际上是:每一层都有遗憾,每一层都有你明知道不够好但没有时间再打磨的地方。RLS 还没做完,使用文档还很粗糙,前端有些交互你自己看着都皱眉头。

但整件事跑通了。从一个用户注册,到建模型,到用 CLI 查数据,到交给 AI 自动完成——这条链路是通的,是真实可用的。

我后来想明白了:「搞定全链路」的意思,不是每一层都做到最好,而是每一层都做到「足以让下一层站上去」。 地基不需要最完美,只需要足够稳;前端不需要最漂亮,只需要让用户能完成任务。全链路是一个系统,不是一堆独立作品的集合。

这个认知转变,花了我八个月。


但我想说的不只是我自己。

AI Coding 兴起之后,我见过很多人在讨论:独立开发者的黄金时代来了吗?

我的看法是:来了,但门槛变了。

以前独立开发的瓶颈是执行力——你一个人,写代码的速度就是上限,很多事情你想做但来不及做。AI 把这个瓶颈大幅拉高了,今天一个人能做的事,放在五年前可能需要一个小团队。

但新的瓶颈出现了:判断力。

AI 可以帮你写代码,但它不知道什么是你的主线任务。AI 可以帮你出方案,但它不知道哪个边界你必须守住。AI 可以帮你做设计,但它不知道你的产品想传递什么感觉。

这些判断,只能来自你自己的积累——你踩过的坑,你处理过的工单,你见过的失败案例,你在某个深夜盯着一行旧代码忽然想明白的那一刻。

AI 降低了执行的门槛,但它同时抬高了判断的价值。 你的经验、你的审美、你对问题的理解,在 AI 时代变得比任何时候都更值钱——因为它们是 AI 唯一无法替代的部分。

所以如果你也有一个「总觉得这件事可以做得更好」的想法,一直压在心里没有动手——

现在是最好的时机。

不是因为 AI 会帮你把所有事情做好。而是因为 AI 第一次让「一个人走完全链路」变成了一件可以认真对待的事。


Modelcraft 是我走完这条路交出的第一份答卷。不完美,但完整。

这就够了。