4天,96小时,我如何从0到1构建一个可演进的个人网站
前言
此次文章源于一次面试课题;在收到这次面试课题时,我面临的不仅仅是“在 96 小时内交付一个个人网站 Demo”的任务。作为一名产品经理,我习惯于从成本与收益的角度审视开发流程:如果只是通过对话让 AI 堆砌代码,虽然起步极快,但随着功能的叠加,系统复杂度和vibe coding途中产生的技术债务会迅速增加,最终陷入“修一个 Bug 产生两个 Bug”的极大混乱当中。
我问了自己一个问题: 在 AI 已经能写代码的今天,产品经理的核心竞争力是什么?是写出更漂亮的 Prompt 吗?
第二个问题则是,在程序员尝试与AI进行结对编程,提升工作效率,发展出无数个人最佳实践的今天,产品经理又可以利用AI IDE和AI CLI 去做些什么呢?
为了回应那两个追问,我决定改变打法。我不再单纯追求“写出代码”,而是追求定义协作系统。
定义边界
1.1 写代码前,先定义边界
在真正开始写代码之前,我先问了自己一个问题:
我到底要做一个“博客”,还是一个“个人品牌平台”?
这两个词看似相似,但产品边界完全不同。如果只是博客,目标很简单:能写文章,能展示内容,能做SEO优化。
针对这一目标,我完全可以使用Notion + github 发布;
但如果目标是一个个人品牌平台,那问题就可能复杂得多,不代表这四天我需要那么多能力,但是在有朝一日的未来,它也很可能需要这些能力:
因此,目标是什么,决定我们要预留哪些能力和空间,以及关联决定到我们使用何种方案,以多少成本去实现它。
1.2 我的决策:只解决当前阶段的问题
我给自己设定的边界是:
第一阶段只做“知识型网站”。
我给它的期望很简单,能放我的文章和我的个人名片,结构清晰,交互清楚,但是它可以在未来做长期演进,让它承载复杂的东西,它也能做到;而不会因为前期设计不足的问题推到重来。
我认为技术背景的同学做产品很可能会遇到这种陷阱,如一开始就考虑设计最终版本,追求高度工程化和大而全的功能。在这个项目里面,我决定做的第一件事,就是:限制问题规模 , 因为只有先定义边界,后续所有技术决策才有意义。
我与AI的协作方式
为什么拒绝“开箱即用?”
大多数人使用 AI IDE(如 Trae 或 Cursor)时,习惯于碎片化的指令。但这会导致三个致命问题:
一个项目如果没有原则,很容易在执行过程中变成“想法集合”。
我的做法1 —— 三点定面
这个词听上去很玄乎,不过笔者要分享的,其实是一个非常简单的初始化模型:
核心页面 × 技术栈 × 审美风格

只要有这三点明确,项目/原型就很难再跑偏。
但如何得出三点结论呢?这需要先问几个产品层面的问题:
这次的目标其实很明确,是一个个人品牌门户的 MVP,用来表达个人方法论和项目思考。用户也很清楚,短期是面试官和同行,他们需要在很短时间内判断我的结构能力和产品思维。商业价值也不复杂,短期是提升竞争力,长期是沉淀个人品牌资产。至于投入成本,这是一个个人项目,我不可能无限期打磨,所以复杂度必须可控。
目标明确之后,我选择在网站的表达上刻意做减法。以首页为例,作为入口页,它的定位应该是信息量高度浓缩的。因此,我先强调身份定位,用姓名与职业标签建立第一印象,再通过领域标签快速传达关注方向,让访问者在几秒内形成关于我的认知;随后用按钮做路径分流,分别引导到文章、履历或关于页面。最后,我选择把最新文章前置,是因为在当前阶段,内容输出才是网站的核心资产。

这些问题想清楚之后,很多想法自然被筛掉了。比如用户系统、数据库、内容管理面板,这些都不是当前阶段的核心价值。于是我把问题收敛到三个点:核心页面、技术栈、审美风格。
核心页面只保留最小表达结构:首页说明定位,文章页承载内容,关于页展示方法论,履历页作为展开版简历展示。只要这四类页面清晰,网站就成立了。技术栈围绕目标选择,生态友好、易部署、成本低、可长期维护即可;审美风格也是一样,如果目标是清晰表达,那就选择克制、干净、信息优先的设计。
当这三点确定下来,整个项目其实就已经有了一个稳定的平面。后面不管加什么功能,都是在这个平面上扩展,而不是推翻重来。
我的做法2 —— 文档先行
在真正开始实现页面之前,我没有急着写代码。
我先做了一件更重要的事情:为 AI 构建了一个结构化的工作空间。很多人把 AI 当成“随时提问的聊天工具”。但如果把它当成一个协作者,那么它一定需要:规则、上下文、项目的约束、项目演进的记录和日志……
做这件事不用一开始就过度设计,铺张浪费;先从这样的结构开始:
├── .agent/
│ ├── rules/
│ │ ├── base_rules.md
├── AGENT.md
├── workflow.md.agent/ 是整个 AI 协作的核心。它不是代码目录,而是规则目录。在这里,可以优先定义项目级的基础规范,打个比方:
# 4. 前端开发规范
## 4.1 技术栈标准
### 核心框架
- **框架**: Next.js 14 (App Router)
- **语言**: TypeScript
- **样式**: Tailwind CSS
- **动画**: GSAP (SVG/复杂动画) + Framer Motion (UI 动画)
- **主题**: next-themes
- **内容**: Markdown + gray-matter
### 依赖安装注意
- react-leaflet 存在 peer dependency 冲突,使用 `--legacy-peer-deps` 标志
- 客户端专用库使用 `next/dynamic` 配合 `ssr: false` 避免 SSR 错误
……此外,在rules里面,一样也可以告诉AI如何与我协作,可以让它每次完成任务时主动检查需求有没有全部完成、也可以要求它不只解决问题,也提出优化建议;当你需要快速修复某些问题的时候,也可以让它干就完事,不啰嗦那么多。
更进一步地,你还可以写一份workflow.md,要求AI用什么样的方式去工作,例如遵循发现问题即记录到工作流程;或者让 AI 主动使用本地md去追踪任务;而非单纯依赖自己的记忆。
AGENT.md就相当于项目的外挂知识,是所有AI记忆不可靠的情况下,需要外挂到本地文件的重要知识,例如:
当然,倘若你的项目足够复杂;也可以拆分到不同目录当中,这一思路来自于 OpenSpec 这个工具,它为每个变更都创造了spec,task等文件,用于约束项目和追踪完成情况。
对于简单项目,很的情况下我不希望自己的工作区当中创建了太多目录,所以,用一个文档去记录足够;如果担心它的篇幅过长,可以定期地让 AI 去清理和压缩这个文件记录的内容;例如,告诉它,删去已经完成的待办任务、将遇到的问题归纳为常见问题和对应解决方法、把关键决策总结为这个项目中你认为的最佳实践。我们可以同样用这些方法去管理 PRD 的撰写。
为什么这么做?因为AI本身没有项目意识,如果没有结构,它每一次对话都像第一次协作。而这种做法;相当于一种复利工程,每一次临时对话通过再加工,都能变成长期协作的默契。
我的做法3 —— 精确表达
在与 AI 协作的过程中,我逐渐意识到一个问题:大多数“AI 不好用”的体验,并不是因为模型能力不足,而是因为输入本身过于模糊。当需求表达是松散的、感性的、带有隐含假设的,AI 只能基于猜测生成结果;而猜测意味着返工,返工意味着成本。于是,我开始在某些复杂需求中引入一种结构化表达方式 —— EARS(Easy Approach to Requirements Syntax)。
在我的网站构建过程中,我曾为页面加入深色模式功能。
如果用普通表达,我可能会这样写给 AI:
给网站加一个黑夜模式,支持切换,界面看起来舒服一点。
如果改用 EARS 结构,这一句话会分解成多条需求语句:
页面首次加载时,系统应检测用户的操作系统级颜色偏好,并据此设置主题。
当用户点击主题切换按钮时,系统应在浅色模式与深色模式之间切换。
主题变更后,系统应将选定模式存储于本地存储,并在后续访问时覆盖操作系统偏好设置。
...
注意,这里每一句都是可测试的,这就意味着需求在提出之时就已经自带测试逻辑。
如果用 EARS 提前将隐含条件显性化,沟通成本会明显下降。更重要的是,这种表达方式会倒逼我在向AI提复杂需求的时候思考:触发条件是否完整?是否存在边界情况?是否存在状态冲突?
当然,如果你暂时没有精力去将所有“一句话需求”拆解为这种规格化的语言,一种提效的方式是将拆解的原理写进面向 AI 的workflow.md 里,就像这样:
## 4. 模糊需求转清晰
### 4.1 EARS 句法
EARS 句法是一种将模糊需求转化为清晰需求的方法,包含固定句式,比如“当…时…应…”,“在…情况下…应…”。在 EARS 句法中,需求必须具备以下要素:零个或多个先决条件、零个或一个触发器、一个系统名称以及一个或多个系统响应。
### 4.2 EARS 模式
#### 1. 通用性需求
在系统的运行过程中都需要满足的功能需求。它们不受事件或输入调用影响,适用于系统的所有操作状态,而不仅仅是某个特定状态下的需求。
**模板**:xxx 应该 xxx
**示例**:手机的质量应该小于 XX 克。
.... (中间略)
### 4.3 模糊需求转清晰的步骤
1. **分析模糊需求**:理解模糊需求的含义和目标
2. **选择合适的 EARS 模式**:根据需求的类型选择合适的 EARS 模式
3. **填充模板**:将模糊需求填充到选择的 EARS 模式模板中
4. **验证需求**:检查需求是否清晰、可实现、可测试
### 4.4 示例
#### 模糊需求
“多语言模式,点击首页右上角按钮可以切换,记住用户的偏好”
#### 清晰表达(使用 EARS 框架)
- 拆解需求要素:
- 前提:系统支持多语言功能
- 触发:用户点击首页右上角按钮并选择新语言
- 系统:网站系统
- 响应:立即更新当前页面语言并持久化保存该语言偏好
- 调用模板:在 [前提] 情况下,当 [触发] 时,[系统] 应 [响应]
- 结果:
\```
在系统支持多语言功能的情况下,当用户点击首页右上角按钮并选择新语言时,网站系统应立即更新当前页面语言并持久化保存该语言偏好。
\```这不是新鲜玩意,这其实就来自于 PRD 编写当中业务规则制定的语法;
当然,万事万物都要回归本质;方法是用来解决问题的,在具体实践当中,并非所有情况下我都会要求AI将我的需求拆解成 EARS,仅当我面对复杂的需求时,这一步才可能有必要性,切忌把简单问题复杂化。
我的做法4 —— 在稳定结构上逐层加固
在做这个网站的时候,我很清楚一件事:如果一开始就想把所有想法都实现,最后一定会乱。
我完全可以在第一天就把深色模式、SVG动画、评论区、摘要、数据统计都加上,但那样的结果通常是结构被不断推翻,代码越写越不敢动。很多个人项目不是做不出来,而是因为一开始设计得太满,后面每加一个功能都要牵一发动全身。
所以我给自己定了一个简单的推进方式:每一轮只解决一个层级的问题,而且必须保证当前版本是稳定的。
第一层很简单,就是让网站能稳定跑起来。页面结构清晰、路由正常、Markdown 可以渲染、能部署成功。这一层的目标不是好看,也不是高级,而是“可运行”。如果连这个都没站稳,后面的优化都是空谈。
当基础结构稳定之后,我才开始做第二层,也就是体验层。比如加入深色模式,优化阅读排版,增加轻微的过渡动画。
逐层推进后,我几乎没有经历“全面重构”。每一次修改都是增量调整。这带来了两个明显好处:
第一,心理负担降低。
第二,决策更理性,可以避免很多过度设计问题。
当你知道下一步只是“加固”,而不是“重写”,整个项目的复杂度会大幅下降。
我的做法5 —— 完成任务之余记得沉淀经验
前面提到的工作区结构、规则目录、workflow,其实并不是一开始就设计好的。
很多东西都是在实践中慢慢长出来的。
一开始,我只是想让输出稳定一点,于是写了几条排版规则;后来发现表达总是模糊,于是加了需求表达规范;再后来觉得结构容易散,就找了几篇文章学习了一下,开始固定输出结构。它并不是一个“设计好的体系”,而是在不断踩坑中逐步补齐的。
有时候我脑子里会有一个想法,但不知道该怎么规范表达。这时候我不会强行写成正式规则,而是先把草稿丢给 AI,让它帮我整理成更清晰的表达,再根据实际使用效果去调整。好用的,就留下来;不好用的,就删掉。
这种方式很像写代码:先写一个能跑的版本,再优化成可复用的版本。
我后来慢慢意识到一个问题——如果这些规则只存在于对话里,那它们其实随时都会消失。一次对话结束,经验就断了。下一次协作又要从头适应。所以我开始刻意把这些“好用的表达方式”、“有效的规则”、“踩过的坑”整理进 AGENT.md,或者写进 rules 目录里。哪怕只是几行总结,也比留在聊天记录里强。
这样做的好处是,它们可以跨对话存在。下一次开始新的任务时,不需要重新解释风格,也不需要重复强调表达方式。规则已经在那里,AI 可以直接遵循。

迭代过程:踩过的坑
1. 关于任务遗忘:AI 并不会主动承担项目责任
最早期的协作里,我常常发现一个现象:上一轮对话中明确提到的待办事项,在几轮讨论后就被自然淹没了。AI 会认真完成当前问题,但它不会主动提醒“还有哪些问题没解决”。这并不是能力问题,而是它根本没有“项目意识”。
解决这个问题的关键,不是要求模型记得更多,而是让它把一切都写下来。我参考了 OpenSpec 的做法,把 todo list 和 checklist 机制引入到 workflow 里,并且强制要求每次任务结束时输出“未解决问题清单”。这些未解决问题不会停留在对话里,而是必须被记录到 AGENT.md 中。换句话说,AI 不负责记住事情,它负责把事情落到文件系统里。只有文件系统才是长期记忆。
## 3. 任务追踪方式
### 3.1 Markdown 勾选框追踪
- [ ] 任务 1:描述
- [x] 任务 2:描述(已完成)
- [ ] 任务 3:描述
### 3.2 当前 3 个最重要的进行中事项
- 保持任务列表简洁
- 优先处理高优先级任务
- 定期更新任务状态
2.关于一次性给太多任务:克制我的输入
另一个明显的问题,是当我一次性抛出大量需求时,输出质量会迅速下降。结构开始混乱,边界开始模糊,甚至出现漏项或轻微幻觉。后来我逐渐意识到,问题并不在模型能力,而在于我给它的任务复杂度远远超出了单次稳定输出的上限。
解决方式并不复杂,但需要纪律——任何复杂目标,都必须先拆解为可执行的子任务,再逐个推进。我把“先拆解,再执行”写进了 workflow 里,作为强制动作。如果一个目标无法在三到五个子任务内被解释清楚,那么说明目标本身还没有被理解,或者这不是一个边界清晰的需求。
3.关于长上下文:有意识地压缩上下文
长会话是另一种隐性风险。当上下文不断增长,早期决策被淹没在我们的长篇大论中,模型虽然“记得”,但注意力可能早就被稀释了。我经历过几次典型场景:同一个项目,前面讨论得非常清晰,但到后面突然开始偏离方向。
真正有效的做法不是依赖更长的上下文,而是定期做摘要沉淀。每当对话进入一个阶段节点,我会让 AI 总结核心决策、原则和未解决问题,并把它们写进 AGENT.md。这样做的意义不只是在于节省 token,而在于重新聚焦。每一次摘要,都是一次主动重置讨论重心的动作。
4.关于工具脚本与自然语言:不要把一切都交给对话
当我们把所有操作都交给自然语言去驱动时,系统就失去了确定性。自然语言适合描述目标、讨论结构、拆解逻辑,但它并不擅长管理环境状态。环境是有副作用的,有历史的,有上下文依赖的,而对话本身是无状态的。每一次“帮我跑一下项目”都是一次重新尝试,而不是一次受控的执行。
举个典型的例子;有一次,我在 Next.js 项目中反复遇到奇怪的运行异常。后来排查发现,是因为在不同端口多次启动开发服务器,导致环境状态混乱。而 AI 很喜欢自动执行 npm run dev,它认为这是“帮你推进”。
问题不在命令本身,而在于没有环境约束。解决方法很简单:写一个统一启动脚本,强制清理占用端口,并固定使用单一端口启动项目。同时在规则中明确禁止 AI 直接执行 run dev,只允许通过该脚本启动。
这个做法看似简单,却改变了协作的性质。原本是“对话直接控制环境”,现在变成了“对话调用工具,工具管理环境”。前者依赖模型的即时判断,后者依赖可重复的确定性逻辑。两者并不是互相替代,而是互相配合。
写在最后
当我回头看这个项目时,我发现自己的判断标准已经悄悄发生了变化。最初我关注的是输出速度和形式质量,后来我开始关注结构是否清晰,再后来我开始关注系统是否稳定。现在我更关心的是,当我离开这个项目一周甚至一个月,在未来想继续长期维护它的时候,我能否无痛地继续接手它。
最后,我还想回答我开头提到的两个问题,仅个人的一些浅见。
如果把 AI 当成能力放大器,那么 Prompt 技巧确实重要,但它永远只是操作层面的技能。真正决定协作质量的,并不是一句 Prompt 是否优雅。
AI 可以生成内容,但它不会天然理解项目节奏,不会主动承担长期责任,更不会自动构建秩序。谁来定义规则,谁来决定记录方式,谁来控制推进节奏,这些问题不会因为模型能力提升而消失。
所以,在 AI 重构了我们的工作流程的今天,产品经理的核心竞争力,并不在于“写得更好”,而在于“判断什么应该被写下来、什么必须被拆解、什么需要被沉淀”。在这个项目里,我真正做的不是优化 Prompt,而是为协作建立一层稳定的框架:任务如何记录,复杂目标如何分段释放,环境如何被工具化管理,阶段性决策如何被固化进文件系统。这些看似琐碎的动作,其实是在回答一个更底层的问题——当效率被放大之后,如何避免混乱同样被放大。
至于第二个问题,当程序员用 AI 提高编码效率时,产品经理是否只能旁观?我的理解恰恰相反。程序员用 AI 优化的是位于执行层的效率,而产品经理可以利用 AI IDE 和 AI CLI 去设计协作层的结构。AI 不仅可以生成代码,也可以帮助产品经理梳理需求、沉淀决策、搭建规则体系、设计验证流程。更重要的是,它可以被用来构建一种可复用的工作方式,而不仅仅是完成一次性任务。

推荐阅读
如果你对本文讨论的软件相关从业人员如何与AI协作这一主题感兴趣,可以延伸阅读以下几篇文章。它们从不同角度讨论了同一个问题:如何在智能工具变强之后,重新定义人类的角色:
Effective harnesses for long-running agents
Shipping Sora for Android with Codex
Adopting the EARS Notation to Improve Requirements Engineering