Skip to content
CloudZun
Go back

从原型到产品:vibe-ecommerce 迭代系列(一)— 规划框架与 Phase 2 实施

编辑此文章

从原型到产品:vibe-ecommerce 迭代系列(一)

规划框架与 Phase 2 实施实录

这是 vibe-ecommerce 项目迭代系列的第一篇。

上一篇我们记录了用 OpenCode + Superpowers 从零构建电商原型的过程,也总结了 7 Gate 质量流程。原型跑通了,但它只是一个 demo——商品图片是随机占位图,没有搜索,没有订单确认,没有后端。

这篇文章记录的是:我们如何把一个 demo 系统性地演进成一个真实产品。重点不是功能本身,而是我们用什么框架来规划演进路径,以及流程本身在迭代中如何优化


一、为什么需要一个演进框架

Vibe Coding 的原型阶段有一个特点:速度快,但方向感弱

你可以在 40 分钟内生成 900 行代码,但这 900 行代码的技术债在哪里?下一步该加什么功能?什么时候该引入后端?什么时候该重构?这些问题,Vibe Coding 本身不回答。

我们参照 LAB-14 Capstone Project 的五阶段框架,为 vibe-ecommerce 制定了完整的演进路线。


二、演进路线图

整体架构演进

Phase 1(当前)          Phase 3 之后              Phase 4 之后
Vercel(前端)    →     Vercel(前端)      →     Vercel(前端)
localStorage          API 请求                   API 请求(JWT)
                       Linux 服务器(后端)        Linux 服务器
                       SQLite/PostgreSQL           PostgreSQL(用户/订单)

六个阶段规划

阶段目标关键产出
Phase 1Vibe Coding 快速原型927 行代码,完整购物流程,已部署
Phase 2前端功能完善搜索/排序/详情跳转/订单确认
Phase 3引入后端Node.js + Express + SQLite,商品/订单 API
Phase 4用户认证JWT 登录注册,订单历史,权限控制
Phase 5性能优化 + 安全加固图片懒加载,API 限流,HTTPS
Phase 6SDD 重构四层文档,模块边界清晰化

技术选型决策记录

Phase 3 后端选型我们选择 Node.js + Express + SQLite,理由:

决策原则:哪个更简单用哪个。过早引入复杂技术栈是 Phase 1 的典型陷阱。


三、流程升级:从 7 Gate 到上下文文档驱动

上一版流程的问题

我们在上一篇文章建立了 7 Gate 流程,核心是:Gate 由架构师把关,不依赖模型自觉遵守

但 7 Gate 流程有一个隐性问题:Gate 是检查点,不是上下文。AI 在执行时仍然缺乏足够的项目背景,容易产生”功能正确但不符合项目约束”的代码。

LAB-14 带来的新工具:上下文文档

LAB-14 引入了 Shopify CEO 风格的上下文文档概念,五个维度:

维度核心问题
① 项目背景当前状态是什么?
② 之前尝试过什么上一阶段做了什么?遇到了什么问题?
③ 成功与失败的定义本阶段结束时,什么算成功?什么算失败?
④ 谁会受影响这次改动影响哪些功能/用户/模块?
⑤ 约束条件技术约束、时间约束、不能破坏什么?

关键认知:上下文文档不只是思考工具,它直接成为给 OpenCode 的 Prompt 上下文。写好上下文文档的 AI 输出质量,远高于随手写的 Prompt。

升级后的流程

[上下文文档] → [GATE 0 BRIEF 确认]

[GATE 1 实现计划]

[GATE 2 执行(每 task 验证)]

[GATE 3 结构验收] → [GATE 4 Spec Review] → [GATE 5 Quality Review]

[GATE 6 修复验证] → [GATE 7 部署]

上下文文档在 GATE 0 之前完成,它是整个流程的”地基”——让后续所有 Gate 都在同一个认知框架下运行。


四、Phase 2 实施过程

Step 1:写上下文文档(GATE 0)

在动任何代码之前,先写 docs/briefs/2026-03-04-phase2-frontend.md

## 项目背景
纯前端 Vanilla JS SPA,hash-based 路由,10 个电子产品,localStorage 购物车。
已修复:XSS、localStorage 崩溃、路由 404、负数数量。

## 之前尝试过什么
Phase 1 完成了完整购物流程,但存在:
- 产品列表卡片没有点击进入详情页的入口
- Mechanical Keyboard 图片链接无效
- 没有搜索功能,没有排序,没有订单确认页

## 成功与失败的定义
- 成功:商品卡片可点击、搜索实时过滤、排序正常、订单确认页显示
- 失败红线:不能破坏现有购物车逻辑,不能引入新的 XSS 漏洞

## 约束条件
- 纯 Vanilla JS,无框架,无构建工具
- 不能动:router.js 核心逻辑、CartStore 接口
- 所有用户输入必须经过 escapeHtml()

这份文档的价值在于:它把”不能破坏什么”和”什么算完成”同等重要地写下来。大多数 Prompt 只说要做什么,不说不能做什么。

Step 2:生成实现计划(GATE 1)

5 个 Task,每个 2-10 分钟,每个有明确验证方法:

Task内容验证方法
1修复 Mechanical Keyboard 图片curl 图片 URL 返回 200
2商品卡片点击进入详情页点击卡片非按钮区域能跳转
3搜索框实时过滤输入 “head” 只显示 2 个商品
4商品排序选价格升序后商品按价格排列
5订单确认页结账后跳转确认页,购物车清空

Step 3:执行细节

Task 1:验证命令先行

修复图片 URL 的第一步不是改代码,而是先验证新 URL 是否有效:

curl -s -o /dev/null -w "%{http_code}" \
  "https://images.unsplash.com/photo-1541140532154-b024d705b90a?w=400&h=300&fit=crop"
# 200 ✓ 再写进 data.js

这是 Gate 2 “每 task 完成后立即运行验证命令”的具体体现——先验证,再提交。看起来多了一步,但它防止了”图片 URL 写进去了但 404”这类低级错误在后续 review 才被发现。


Task 2:事件冒泡陷阱

商品卡片整体可点击,但 “Add to Cart” 按钮不能触发跳转。解法是 event.stopPropagation()

// 卡片整体点击 → 进入详情
<div class="product-card" onclick="Router.goTo('product-detail', {id: ${product.id}})">
    ...
    // 按钮阻止事件冒泡,只触发加购
    <button onclick="event.stopPropagation(); ProductsPage.addToCart(${product.id})">
        Add to Cart
    </button>
</div>

这是一个典型的”功能正确但交互细节容易遗漏”的场景。上下文文档里写了”不能破坏现有购物车逻辑”,这个约束让我们在设计时就主动考虑了这个细节,而不是等 bug 出现再修。


Task 3+4:计划 vs 执行的合理偏差

计划里 T3(搜索)和 T4(排序)是两个独立 Task,执行时合并成了一个。原因是它们共用同一套状态:

const ProductsPage = {
    currentCategory: 'all',  // 分类过滤
    searchQuery: '',          // 搜索关键词
    sortOrder: 'default',     // 排序方式

    getFilteredProducts() {
        let products = /* 按分类过滤 */;
        if (this.searchQuery) products = /* 按关键词过滤 */;
        if (this.sortOrder !== 'default') products = /* 排序 */;
        return products;
    }
}

为什么合并状态而不是分开管理? 因为合并后 mount() 成为唯一的渲染入口——无论是搜索、分类还是排序触发的更新,都走同一个渲染路径,不会出现”搜索后分类状态丢失”这类状态不同步问题。

这也说明:计划是指导,不是教条。当执行时发现两个 Task 有天然的合并理由,合并是正确决策——但要记录理由,不是随意跳过。


Task 5:存储方案的架构决策

订单确认页需要在页面刷新后仍然可访问(用户可能想截图保存)。有三种方案:

方案问题
URL 参数传递订单数据订单信息暴露在浏览器历史记录和服务器日志
localStorage 持久化数据永久保留,用户清理购物车后订单仍在,语义混乱
sessionStorageTab 关闭后自动清除,符合”临时查看”语义,不跨 session 持久化

选 sessionStorage 的核心理由:语义匹配。订单确认页是一次性的临时状态,sessionStorage 的生命周期和这个语义完全吻合。这个决策记录在上下文文档里,Phase 4 引入后端后,这里会替换成真实的订单 API——到时候不需要重新推导,直接看记录就知道当初为什么这样设计。

Step 4:验收(GATE 3)

# 语法检查
node --check js/components/order-confirmation.js  # OK
node --check js/components/checkout.js            # OK
node --check js/components/products.js            # OK

# 路由注册检查
grep -c "Router.register" js/components/*.js
# 每个组件都有且只有一个 register ✓

# 串联检查
grep "order-confirmation" index.html              # script 标签存在 ✓
grep "order-confirmation" js/components/checkout.js  # Router.goTo 存在 ✓

五、流程本身的优化:这次学到了什么

优化 1:上下文文档让”失败红线”和”成功标准”同等重要

传统 Prompt 只说”做什么”,上下文文档强制你同时思考”不能破坏什么”。这个改变让 Phase 2 的执行过程中没有出现任何回归问题——因为约束在执行前就已经明确。

优化 2:计划粒度决定验证质量

Phase 1 的任务粒度是”实现购物车模块”(太大),Phase 2 的任务粒度是”商品卡片点击进入详情页,验证:点击非按钮区域能跳转”(刚好)。

粒度越细,验证越具体,越不容易出现”功能实现了但边界条件没处理”的问题。

优化 3:技术决策要记录理由,不只记录结论

我们在上下文文档里记录了”为什么选 sessionStorage 而不是 URL 参数”。这不是给 AI 看的,是给未来的自己看的——下次迭代时,你能快速理解当时的约束,而不是重新推导一遍。

优化 4:Qwen 模型的 HARD-GATE 遵守问题有了新解法

上一篇文章提到 Qwen 会跳过 Superpowers 的 review 步骤。这次我们的解法是:把 review 步骤内化到上下文文档的”失败红线”里,而不是依赖模型自觉触发 skill。

效果:Gate 5(Code Quality Review)这次没有发现新的 CRITICAL 问题,说明上下文文档的约束条件确实在执行阶段起了作用。


六、当前状态与下一步

Phase 2 交付物

Phase 3 预告

下一篇将记录引入后端的过程:Node.js + Express + SQLite,把商品数据从硬编码迁移到 API,购物车状态迁移到服务端,订单写入数据库。

这是整个演进路线中最关键的一跳——从纯前端静态应用变成有状态的全栈应用。架构变了,部署方式变了,测试方式也变了。上下文文档在这个阶段的价值会更加凸显。


资源


编辑此文章
Share this post on:

📚 相关文章推荐


Previous Post
HN Daily Digest: 2026-03-05
Next Post
Vibe Coding 的质量陷阱:为什么你需要 7 个 Gate