ScholarFlow 原本只是我想认真做完的一个全栈项目:一个面向学术出版流程的现代化工作流系统,前端用 Next.js,后端用 FastAPI,数据库放在 Supabase,前端部署在 Vercel,后端跑在 Hugging Face Spaces。
但项目做到后面,我越来越清楚地意识到:它带给我的最大收获,不只是做出了一个系统,而是让我重构了自己和 AI 协作开发的方式。
60 秒介绍
如果面试官只给我 60 秒介绍这个项目,我会这样说:
ScholarFlow是一个学术出版工作流系统,我用它来验证一套更适合 AI 协作开发的工程方法。最初我围绕 “AI-friendly” 做技术选型,所以选择了FastAPI + Next.js + shadcn。中途我发现,真正的难点不是写代码,而是把模糊需求澄清成可执行方案。后来我开始把需求澄清本身交给 CLI agent 和 skills 去做,并逐步从 GUI 型 AI 工具转向Claude Code / Gemini CLI / Codex / Context7这类更可组合的工作流。这个项目让我真正学会的,是怎么在复杂需求、AI 工具和工程约束之间做判断。
一个看起来像“全栈项目”的东西,为什么会变成方法论实验
从功能上看,ScholarFlow 并不简单。
它不是一个普通的 CRUD 后台,而是一个带有明确状态流转和角色边界的系统:
- 作者提交稿件,并触发解析与校验
- 编辑推进审稿和修改流程
- 审稿人与作者在不同阶段看到完全不同的界面和动作
- 系统还需要处理通知、财务闸门、AI 辅助匹配、统计分析和内容门户
从仓库本身也能看出这个复杂度。项目很早就不是“几个页面 + 一个 API”那么简单,而是迅速长出了:
- 成体系的
specs/ - 大量工作流设计和 handoff 文档
- 明确的状态机、流程图、顺序图
- 针对审稿、作者修回、邮件编排、生产 SOP 的持续硬化
也正因为它足够复杂,它才逼着我不断修正自己的开发方式。
仓库证据
这不是纯回忆,我能在仓库历史里直接看到这条演进线:
a35755b:从Specify template起步,不是从空白仓库起步3e232ce到6b0d32e:投稿、编辑、审稿、财务闸门、AI reviewer recommendation 先后落地f10df9d、eaef652、e138844、6ef15b9、ec6aae4:抄袭检查、门户重设计、内容生态、认证和 QA 套件逐步补齐b2780e8:编辑工作台变成真正的操作台89f405b、a62deac、e945de0、fe72fd5、c4470a1:测试、staging、部署和生产发布闸门不断硬化
这条线很重要,因为它说明 ScholarFlow 不是“先做出来再说”的小玩具,而是一直在向真实系统靠拢。
这条线也解释了为什么我后面会越来越在意测试、handoff、workflow 文档和生产 SOP。项目不是一次性写完的,而是一直在被推进成一个更真实、更可运营的系统。
为什么我一开始会围绕 “AI-friendly” 做技术选型
我一开始对技术选型的判断,很大程度上是围绕一个问题展开的:
“如果我要和 AI 长时间协作开发,这套栈是不是足够友好?”
这听起来有点反直觉,但当时对我来说很现实。
后端:为什么是 FastAPI
我很早就意识到,AI 在 Python 这条线上是天然强势的。
而 ScholarFlow 的后端又不只是简单的增删改查,它还涉及:
- 文本处理
- 一些 NLP 相关能力
- API 编排
- 与外部服务和本地模型能力的结合
在这个前提下,FastAPI 对我来说几乎是顺理成章的选择。
它足够现代,类型提示清晰,和 Python 生态的结合也非常自然。更重要的是,在和 AI 协作时,FastAPI 的写法、结构和常见问题都更容易被准确理解和扩展。
前端:为什么是 Next.js
前端我选择了 Next.js,原因也类似。
AI 在 TypeScript + React 上同样足够强,生态也足够成熟。对我来说,这意味着:
- 组件边界更容易被 AI 理解
- 常见 UI 模式和全栈模式更容易生成
- 和后端 API 的协作更顺手
如果说 FastAPI 是为了后端和文本处理的效率,那么 Next.js 更像是在为“全栈协作效率”买单。
组件系统:为什么是 shadcn
组件库我选择了 shadcn。
这背后的理由其实不神秘:我当时在社交媒体上经常看到一种说法,大意是“这就是当前的版本答案”,而我真正关心的不是口号,而是另一层含义:
AI 对这套组件体系足够熟。
这件事很重要。因为一个 UI 方案如果文档足、示例多、模式清晰、AI 常见,那么它不仅开发更快,后续维护和迭代也更顺。
所以现在回头看,我那时的技术选型并不是“只看性能”或者“只看个人偏好”,而是已经在无意识地围绕 AI 协作效率 做判断了。
而且这件事不是事后硬解释。从仓库历史也能看出来,项目从很早开始就同时维护 AGENTS.md、GEMINI.md、规格文档和 handoff 材料。换句话说,我当时虽然还没有把它总结成“AI-friendly 技术选型”这几个字,但实践上已经在往这个方向走了。
我最早是怎么理解“需求分析”的
ScholarFlow 不是我凭空想出来的产品。
最开始是老板找来一个后续真正会使用系统的甲方和我交接。对方会告诉我:
- 这个系统应该长什么样
- 需要有哪些角色
- 流程应该怎么走
- 哪些环节最容易卡住
问题是,这类交接往往持续很久,而且信息量非常大。
我当时很清楚:如果只是靠当场听、靠记忆回忆,后面一定会丢细节。所以我做了一个我现在回头看仍然觉得很有价值的动作:
- 用手机把整段沟通录下来
- 用通义听悟把语音转成文字
- 再把接近一个多小时的对话内容交给 AI 做结构化整理
- 让 AI 帮我生成
mermaid图,包括:- 时序图
- 状态机图
- ER 图
- 流程图
这一步在当时很有效,因为它帮我把一大坨口头信息,快速变成了更适合工程落地的中间层材料。
如果只停在这里,我可能会把它总结成一句:“AI 帮我提升了需求整理效率。”
但项目继续往下做,我很快发现这还不是问题的本质。
后来我才意识到,真正的问题不是“整理得不够快”,而是“对方自己也没想清楚”
这是 ScholarFlow 给我最大的产品认知冲击之一。
那套“录音 -> 转写 -> AI 整理 -> Mermaid 图”的流程,看起来已经很完整了,但它仍然有一个根本缺陷:
它默认提需求的人已经知道自己想要什么。
可现实并不是这样。
很多时候,对方只能用一种模糊的自然语言描述自己的想法。他知道自己“不满意现在的流程”,也知道自己“大概想要一个系统”,但他未必能在第一次沟通里就把:
- 边界条件
- 角色责任
- 异常分支
- 状态切换
- 真正的优先级
全部说清楚。
而如果我只是把这种模糊表达重新整理一下,再原样转交给 AI,那么问题并不会消失,只会被放大。
我后来越来越确定:
真正需要被 AI 处理的,不只是代码生成,而是需求澄清本身。
所以我开始把“澄清需求”前移成一个独立环节
后来我给对方弄了一个最简单的 Qwen CLI,并且给它装了一个偏 Brainstorm 工作流的 skill。
这个动作对我来说很关键,因为它代表着一个思路变化:
- 以前我的想法是:用户提需求 -> 我理解 -> 我交给 AI
- 后来的想法是:用户先和 agent 来回沟通很多轮,把需求本身打磨清楚 -> 再进入实现阶段
这件事的意义非常大。
它不是在“多加一个工具”,而是在重新设计需求入口。
通过多轮追问、澄清、补边界、暴露矛盾,用户会在沟通过程中自己意识到:
- 哪些地方他还没想清楚
- 哪些流程说不通
- 哪些细节之前被遗漏了
这比我单方面“把录音内容转成文档”要有效得多。
如果让我用一句话总结这段转变,那就是:
我开始意识到,AI 最有价值的地方之一,不是帮我写得更快,而是帮我更早暴露问题。
这也是为什么后来仓库里会越来越多地出现测试、handoff、workflow 文档和阶段性收口记录。因为当我真正接受“问题要尽早暴露”之后,我对项目的关注点就不再只是“功能有没有做出来”,而是“流程是不是清楚、状态是不是可验证、交接是不是可继续”。
从 GUI 到 CLI:我对开发效率的理解也被改写了
在学校里用 AI 写代码时,我最早接触的是那类嵌在 IDE 里的工具,或者直接 Fork 自 VS Code 的产品:
- Trae
- Cursor
- Windsurf
- Cline
- Kilo
- Antigravity
这些工具不是没用。它们让我很早就接触到了 AI 编程,也让我习惯了“通过对话驱动代码”这件事。
但后来我越来越明显地感觉到一个问题:
图形界面并不一定是最高效的 AI 协作方式。
尤其在 Arch Linux 这种环境下,很多操作根本不需要我自己用鼠标去点:
- 看文档
- 改配置
- 装工具
- 跑命令
- 调整工作流
只要 agent 能调用 shell,它往往能直接把这件事做完。
所以后来我逐步转向了:
Claude CodeGemini CLICodexOpenCodeContext7
我开始越来越看重这些工具的几个能力:
- 能不能直接读文档
- 能不能直接跑命令
- 能不能跨项目保持稳定规则
- 能不能和我的本地环境真正形成工作流
这时我对“AI 编程工具”的理解已经发生了变化。
我不再把它们当成“写代码插件”,而是把它们当成可编排的工程协作者。
回头看仓库演进,这个转变也不是抽象感受。比如项目后期不只是代码在增长,AGENTS.md、CLAUDE.md、GEMINI.md、handoff 文档、测试策略和工作流文档也在持续演化。这说明我后来真正优化的,已经不只是代码实现,而是整套协作环境。
我也踩过一个很典型的坑:我曾经以为 skills 越多越好
后来我接触到了 Skills。
说实话,Skills 在 2025 年底其实就已经出现了,只是当时我没有真正理解它,也没有意识到它会成为一条重要路线。很长一段时间里,我对它的态度都是:不知道怎么用,就先忽略。
后来真正开始用之后,我又走向了另一个极端。
我开始频繁安装 skill,经常去问:
- 这个项目符不符合最佳实践?
- 这个任务是不是该触发某个 skill?
- 我是不是应该尽量让 agent 多用 skills?
我甚至一度让本地安装的 skills 接近 200 个。
一开始我很兴奋,因为这看起来像是在不断扩充 agent 的能力边界。
但后来我开始怀疑这条路线是否真的对。
于是我做了两件对我影响很大的事:
- 我不再只依赖 Context7 查文档,而是直接把
Codex、Gemini CLI、OpenCode的源码 clone 下来,让 AI 去读它们的实现,去理解:compress是怎么做的- skills 的机制到底是什么
- 我又看到了 Google 团队的一篇关于 skills 的论文,里面专门讲了:
- 不要把 skills 当成越多越好的收集游戏
- skill 的描述会消耗上下文
- 真正有效的是更 focused、更 procedural、触发冲突更低的 skill
- 选择 skill 时要优先考虑它是否真的能提升验证和执行质量
那一刻我印象特别深。
因为我突然明白,我之前“尽量多装、尽量多用”的策略,其实是错的。
我想要的不是一个塞满说明书的 agent,而是一套经过筛选、能在正确时机触发、真正减少错误的能力层。
这也直接影响了我后来做的另一个开源项目:
我开始系统整理“哪些 skills 值得安装、为什么值得安装、如何按场景分层安装”。
60 秒后的追问
如果面试官继续追问,我会优先回答这三件事:
- 我怎么判断
FastAPI + Next.js + shadcn + Supabase + HF/Vercel是更适合 AI 协作开发的组合 - 我为什么认为“需求澄清”本身比“需求整理”更重要
- 我怎么从“多装 skills”转向“按论文原则筛选 skills”
所以如果让我诚实地概括这段经历,我不会把它说成“我一开始就懂得怎么和 AI 最好地协作”。更准确的说法是:ScholarFlow 让我把很多错误的直觉先走了一遍,然后再逼着我把这些直觉一个个纠正过来。
ScholarFlow 最终教会我的,不只是怎么做系统,而是怎么做判断
如果只看技术实现,ScholarFlow 当然能讲很多:
- 为什么是
FastAPI + Next.js - 为什么要用
Supabase - 为什么前端放
Vercel,后端放Hugging Face Spaces - 为什么需要状态机、邮件流程、财务闸门、AI reviewer matchmaking
但对我来说,这个项目真正重要的地方在于,它逼着我把很多原本模糊的判断系统化了。
我学到的不是“AI 很强,可以帮我写代码”。
我学到的是:
- 技术选型可以围绕 AI 协作效率来做
- 需求整理如果不处理模糊性,再漂亮的文档也没用
- CLI agent 往往比 GUI 插件更适合深度工程协作
- Skills 不是越多越好,而是越合适越好
- 真正成熟的工程判断,往往来自不断纠正自己之前的错误理解
所以如果我要总结 ScholarFlow 对我的意义,我会这样说:
它让我第一次真正把“做产品”“做系统”“做 AI 协作工作流”这三件事,放到同一个项目里一起思考。
而这也正是我现在最希望带到下一份工作里的能力。