用 AI 打造高品质 Web 应用


Key Takeaways
- Vibe Coding 核心理念: 逃离 AI Slop 陷阱
- 五步工作流全景: 从一句话需求到上线部署
- 第一步上: Grilling 会话捕获项目上下文
- 第一步下: Decisions.md 与 Spec.md 双文档契约
- 第二步上: 挑选成熟产品作为克隆骨架
- 第二步下: Deep Research Skill 识别可复用组件
- 第三步: Spec 驱动的 Clone 改造工程
- 第四步上: Impeccable Skill 的四阶段设计哲学
- 第四步中: Git Work Trees 并行多方案试错
- 第四步下: Small / Medium / Large / Surprise Me 四档重塑
- 设计令牌: 用常量变量统一全站视觉
- 第五步: 硬编码审计与暗色模式打磨
- Apple 风格滚动动画: 让页面活起来
- Hixfield.ai 集成: 把 AI 视频装进 Claude Code
- 滚动驱动页面的工程实现与 Storyboard
- 部署到 Cloudflare: 前端一键上线的工程要点
- Vibe Coding 与传统开发的取舍矩阵
- 进阶路线: Vibe Coding 工程师的能力栈与生态
Vibe Coding 核心理念: 逃离 AI Slop 陷阱

AI Slop 的工程定义
观察 当我们让 AI Coding Agent 在零上下文的状态下"自由发挥"时,产出的代码与界面会呈现出惊人的同质化:同一种渐变色 hero 区、同一种圆角卡片、同一种 "Get Started" CTA、同一种千篇一律的 Inter 字体配 Lorem 文本。这种被社区戏称为 AI Slop 的产物,本质上是模型在缺乏产品上下文时,把训练分布里出现频率最高的视觉范式当作"通用解"吐出来。它不是 bug,而是统计意义上的最大似然估计。
把它升格到工程层面来定义:AI Slop 指的是在缺少业务上下文、设计语境和审美约束的前提下,由生成式模型批量产出的、具备高可复制性但缺乏产品级质感的同质化界面与代码。它在 Demo 阶段几乎无可挑剔------能跑、能看、能截屏------但一旦进入真实用户场景,就会暴露出三个致命问题:品牌识别度为零、信息密度极低、交互细节经不起推敲。模型给的从来不是"错的",只是"最常见的"。
Vibe Coding 的核心命题
数据 一份面向 2026 年初 AI 工程师群体的内部调研显示,受访者将"AI 生成的产物能否直接用于生产"列为头号焦虑,占比远高于"AI 会不会取代我"。这恰好对应 Vibe Coding 的核心命题:让 AI 的输出具有产品级质感,而不是停留在 Demo 级炫技。
与传统提示词工程不同,Vibe Coding 把"氛围"------vibe------当作一等公民来经营。它承认 AI 在结构化任务上是优秀的执行者,但在品味判断、品牌叙事、细节打磨上是天生的白板。工程师的工作,就是给这块白板持续供给上下文,让模型每一次输出都踩在正确的 vibe 上。换言之,Vibe Coding 不是更聪明的 prompt,而是更完整的工程纪律。
高品质输出的三要素
把 vibe 落地为可操作的工程变量,可以拆成三块:丰富上下文、成熟模板、设计技能。三者缺一,产物就会滑回 AI Slop。
第一,丰富上下文 。上下文不是越长越好,而是越对位越好。一个高质量的 prompt 必须包含三层信息:业务上下文(目标用户、核心场景、品牌调性)、技术上下文(框架约束、依赖清单、部署目标)、审美上下文(参考站点、色板、字体、组件库)。这三层叠加,模型才能从"通用网页生成器"切换到"为某品牌某业务量身定制的工程师模式"。可以参考 Next.js 官方文档与 shadcn/ui 文档中关于项目结构与设计令牌的章节,作为审美上下文的标准锚点。
第二,成熟模板。与其让模型从零拼装,不如给它一份经过验证的脚手架:Next.js App Router 加 Tailwind CSS 加 shadcn/ui 加 Framer Motion 的组合,本身就是被无数生产项目打磨过的"产品级默认"。模型在这套骨架上做填空,远比在空白画布上做创作要稳,也更容易通过 TypeScript 类型检查与 ESLint 规则。
第三,设计技能。这里的设计技能不是要求工程师会画 Figma,而是要求其具备把模糊感受翻译成结构化指令的能力。能说出"卡片间距用 24px 而非 16px"、"标题字号用 clamp(2rem, 4vw, 3rem)"、"动效用 ease-out 而非 linear",这种把品味量化为参数的能力,就是 2026 年 AI 工程师的核心竞争力。
三条路线的工程取舍
Vibe Coding 不是要取代传统开发,也不是要全盘拥抱 AI 生成。它是介于两者之间的中间路线,价值正在于对风险的精细切分。
bash
# 传统开发的工作流
git checkout -b feat/pricing-page
# 手动写 React 组件、手动调样式、手动写测试
npm run dev
git commit -m "feat: pricing page"
# 纯 AI 生成的工作流
"帮我做一个定价页面"
# 直接复制粘贴产物,几乎不做 review
# Vibe Coding 的工作流
"基于 docs/pricing-spec.md 的需求,
使用 src/templates/pricing 模板,
参考 dribbble.com shots/123 的视觉,
输出三套候选方案,等我们 review"
| 维度 | 传统开发 | 纯 AI 生成 | Vibe Coding |
|---|---|---|---|
| 单页耗时 | 数小时 | 数分钟 | 30 至 60 分钟(含 review) |
| 视觉一致性 | 高(由工程师保障) | 低(取决于 prompt) | 中高(由模板与上下文保障) |
| 可维护性 | 高 | 极低(产物难以追溯) | 中(由 git 与 review 保障) |
| 上手门槛 | 高(需熟手) | 极低 | 中(需会拆需求与挑方案) |
| 主要风险 | 工期 | 同质化、版权、可读性 | 上下文污染、token 泄漏 |
观察 表格中 Vibe Coding 列的"可维护性"被打成"中",不是因为技术做不到高,而是因为大多数团队会跳过 review 这一步,直接把 AI 输出当最终产物。Claude Code 文档里强调的 Plan → Build → Review 闭环正是为了对抗这种偷懒------它强制模型先出方案再动手,并在最后做一次自审,再把产物交给人类工程师做最后一轮 diff 审视。
工程师角色的翻转
如果说 2023 年的关键词是"提示词工程",那么 2026 年的关键词已经变成"上下文工程",也就是"喂上下文"。
具体到工作流上,工程师的角色发生了三重翻转:从写代码转向拆需求,从敲键盘转向喂上下文与挑方案,从单人产出转向人机协作。前两重翻转要求工程师学会把模糊的产品诉求拆解成结构化 prompt;第三重翻转要求工程师把 review 与测试当作核心动作,而不是事后补救。
python
# 一个合格的 vibe coding prompt 结构示例
prompt = {
"context": {
"product": "面向独立开发者的 SaaS 工具",
"audience": "25 至 35 岁,技术背景,审美敏感",
"brand": "极简、专业、带一点 playful",
},
"constraints": {
"stack": "Next.js 14 + Tailwind + shadcn/ui",
"deploy": "Vercel",
"a11y": "WCAG 2.1 AA",
},
"references": [
"linear.app/pricing",
"vercel.com/design",
],
"deliverables": [
"pricing/page.tsx",
"pricing/pricing.test.tsx",
"storybook story",
],
}
这样的 prompt 已经不是"一句话指令",而是一份迷你工程契约。它把 vibe 量化、把约束前置、把交付物明确化,模型才有空间做出产品级的输出。
2026 年 Agent 时代的品味命题
数据 进入 2026 年,Claude Code、Codex CLI、Cursor、GitHub Copilot 等 Agent 产品已经形成稳定的能力分层:在"能不能写"这一维度上,差距正在收敛;但在"写得好不好"这一维度上,差距反而在被拉大。原因是 Agent 的执行能力在趋同,而产品级质感的来源------品味、上下文、设计判断------依然高度依赖人类输入。
这意味着,2026 年的 AI 工程师必须同时修炼两套肌肉:工程肌肉 (懂架构、懂部署、懂测试)与品味肌肉(懂审美、懂用户、懂叙事)。前者决定产物能不能跑起来,后者决定产物值不值得被使用。两者缺一,产出的就是 AI Slop;两者兼具,产出的才是 Vibe Coding。
回到这套课程的立意:它不教你成为提示词高手,而是教你成为能把 vibe 翻译成可执行上下文的产品工程师。在这个意义上,Vibe Coding 不是对传统开发的背叛,而是对它的延伸------它把工程师从敲键盘的体力劳动中解放出来,逼着他们去做只有人能做的事:判断、挑选、打磨。当 Agent 越来越像流水线工人,工程师反而要更像策展人------决定哪些方案值得被留下,哪些该被打回。
五步工作流全景: 从一句话需求到上线部署
五步工作流全景并不是把"AI 写代码"包装成某种神秘黑盒,而是把一段从一句话需求到上线部署的工程流水线,拆解成五段彼此独立、彼此可校验的子任务。每一段只解决一类具体的质量痛点,这种"职责单一"的拆分思路,正是避免 AI Slop 在流水线中段扩散的工程前提。前置一节已经把 AI Slop 定义为"模型在缺乏产品上下文时,把训练分布里出现频率最高的视觉范式当作通用解"------而下面这五步,正是用结构化契约对抗这种统计意义上的最大似然塌缩。

第一步是收集上下文 。当用户输入一句口语化需求,例如"我想做一个面向独立开发者的 SaaS landing page,主打 AI 代码评审",Claude Code 不会立刻开始写代码,而是先在仓库根目录创建 spec.md,把口语化需求转写成结构化的产品契约。这一步的核心产物包括目标用户画像、核心价值主张、关键功能清单、视觉参考链接、竞品清单、技术栈约束、SEO 元信息。痛点是需求模糊、口语化、不可直接执行,且容易被模型自行脑补填补。
第二步是克隆成熟产品 。Claude Code 借助 GitHub MCP server 直接拉取同赛道的开源 landing page,常见选择包括 Tailwind UI 的 marketing 模板、shadcn/ui 官方模板(ui.shadcn.com/docs)、verce...%25E3%2580%2581vercel%2Ftemplates%2C%25E9%2580%259A%25E8%25BF%2587%25E9%2580%2590%25E6%2596%2587%25E4%25BB%25B6%25E9%2598%2585%25E8%25AF%25BB%25E5%2590%25B8%25E6%2594%25B6%25E5%25B8%2583%25E5%25B1%2580%25E4%25B8%258E%25E7%25BB%2584%25E4%25BB%25B6%25E6%25A8%25A1%25E5%25BC%258F%2C%25E8%2580%258C%25E4%25B8%258D%25E6%2598%25AF%25E5%2587%25AD%25E7%25A9%25BA%2522%25E6%2583%25B3%25E8%25B1%25A1%2522UI%25E3%2580%2582%25E5%2585%258B%25E9%259A%2586%25E4%25B8%258D%25E6%2598%25AF%25E6%258A%2584%25E8%25A2%25AD%2C%25E5%2585%258B%25E9%259A%2586%25E6%2598%25AF%25E7%25BB%2599%25E6%25A8%25A1%25E5%259E%258B%25E4%25B8%2580%25E4%25B8%25AA%25E9%25AB%2598%25E5%25AF%2586%25E5%25BA%25A6%25E7%259A%2584%25E8%25A7%2586%25E8%25A7%2589%25E5%2585%2588%25E9%25AA%258C%2C%25E6%2598%25BE%25E8%2591%2597%25E9%2599%258D%25E4%25BD%258E "https://ui.shadcn.com/docs)%E3%80%81vercel/templates,%E9%80%9A%E8%BF%87%E9%80%90%E6%96%87%E4%BB%B6%E9%98%85%E8%AF%BB%E5%90%B8%E6%94%B6%E5%B8%83%E5%B1%80%E4%B8%8E%E7%BB%84%E4%BB%B6%E6%A8%A1%E5%BC%8F,%E8%80%8C%E4%B8%8D%E6%98%AF%E5%87%AD%E7%A9%BA%22%E6%83%B3%E8%B1%A1%22UI%E3%80%82%E5%85%8B%E9%9A%86%E4%B8%8D%E6%98%AF%E6%8A%84%E8%A2%AD,%E5%85%8B%E9%9A%86%E6%98%AF%E7%BB%99%E6%A8%A1%E5%9E%8B%E4%B8%80%E4%B8%AA%E9%AB%98%E5%AF%86%E5%BA%A6%E7%9A%84%E8%A7%86%E8%A7%89%E5%85%88%E9%AA%8C,%E6%98%BE%E8%91%97%E9%99%8D%E4%BD%8E") AI Slop 出现的概率。痛点是模型在零先验状态下,只能产出训练分布里最高频的范式,从而陷入前文所述的"通用渐变 + 圆角 + Inter 字体"的同质化陷阱。
第三步是合并为 v1 。这一步把第一步的需求文档与第二步的代码骨架,在 spec.md 契约下合并产出第一个可运行版本。合并过程会产生大量 diff,Claude Code 内置的自审机制会针对 diff 做一遍 dry run,识别 Hero、Features、Pricing、FAQ、Contact 这五件套是否齐备,字段是否对齐 spec.md。痛点是合并冲突、字段遗漏、关键页面缺失,以及组件层级错配。
第四步是重塑视觉。这一步把通用骨架改造成具备品牌识别度的成品,包括自定义配色、自定义字体、自定义插画位、自定义图标库。这里需要明确禁止使用通用渐变 + 圆角 + Inter 字体的"AI 默认组合",而是把 spec.md 中已经确定的视觉 token 作为唯一依据,任何超出 token 范围的视觉决策都必须先写回 spec.md。痛点是视觉同质化、品牌识别度低,以及改完一处被改回原样的反复回滚。
第五步是滚动动画 。这一步引入 Framer Motion 或 GSAP 来做滚动触发的叙事化动画,目的是让 landing page 在 LCP(Largest Contentful Paint,详见 web.dev/vitals/)之外,...%25E4%25B9%258B%25E5%25A4%2596%2C%25E9%2580%259A%25E8%25BF%2587 "https://web.dev/vitals/)%E4%B9%8B%E5%A4%96,%E9%80%9A%E8%BF%87") INP(Interaction to Next Paint)维度提供差异化体验。动画方案必须写回 spec.md 的 Motion Budget 章节,避免后续迭代时被覆盖或丢失。痛点是静态页面叙事力弱、用户停留时间短、首屏之后注意力迅速衰减。
spec.md 是横跨五步的唯一契约。每一步结束时,Claude Code 必须把决策、链接、字段、token 全部写回到 spec.md 的对应章节。这种"单一事实来源"机制直接解决了上下文漂移(context drift)的根本问题。在传统多轮对话中,模型会在长上下文里遗忘早期指令,导致后续代码与最初需求脱节;而 spec.md 把约束外化为文件,任何一步都可以通过读取 spec.md 重新对齐,而不必依赖容易丢失的对话历史。这也是为什么整条流水线被称作"以契约为轴心的反馈环",而不是简单的串行任务。
下面给出一段 spec.md 的伪代码片段,展示契约的具体结构形态:
markdown
# SaaS Landing Spec v0.1
## 1. Product Brief
- Audience: 独立开发者,5 人以下小团队
- Core promise: AI 代码评审,30 秒内出报告
- Pricing: Free / Pro $12/mo / Team $39/mo
## 2. Visual Tokens
- Primary: #0EA5E9 Accent: #F59E0B
- Font: Geist Sans Mono: JetBrains Mono
- Radius: 12px Spacing: 8pt grid
## 3. Page Inventory
- / /pricing /faq /contact /changelog
## 4. Motion Budget
- Scroll reveal: 240ms ease-out
- Hover transition: 150ms
- Hero entrance: staggered 80ms
每一步都可以在独立的 Claude Code 会话中执行,这是一种工程层面的"噪音隔离"机制。第一步的会话只关心需求文档,不会被上百万 token 的代码库拖慢响应;第二步的会话只读取 GitHub 模板,不会被前序 diff 干扰判断。当第二步发现需求有歧义时,只需回头修改 spec.md,而不是在对话里反复补丁。这种"会话即阶段"的隔离,让每一步的输入输出都可被独立审查、独立回滚,也显著降低了单次会话的 token 消耗。
会话切换的具体执行方式包括:每完成一步,在终端里执行 claude --resume 切换上下文,或者直接开启新会话并通过 /init 命令加载 spec.md 作为系统级约束。Claude Code 的 slash commands 文档详细说明了 /compact、/clear、/init 等命令管理会话生命周期的标准做法,可参考 docs.anthropic.com/en/docs/cla... CI 的 stage 隔离思想。
最终产物是一份部署到 Cloudflare Pages 的高品质前端。Cloudflare Pages 的优势在于边缘 CDN、免费 HTTPS、自动 preview deployment、Wrangler 一键回滚,完整文档见 developers.cloudflare.com/pages。配合 GitHub MCP 的 PR 工作流,每一次视觉迭代都会自动生成 preview URL,设计师和产品负责人可以在浏览器里直接评审,而不必 clone 仓库本地运行。当 spec.md 出现字段变更时,预览链接会立即反映改动,从而把"代码评审"前移到"视觉评审"阶段,缩短反馈回路。
下面用一张对比矩阵展示三种开发范式的关键差异:
| 维度 | 传统开发 | Vibe Coding | 纯 AI 生成 |
|---|---|---|---|
| 上下文控制 | 工程师手动维护 | spec.md 契约化 | 无约束,自由发挥 |
| 视觉同质化 | 中等,取决于设计师 | 低,有品牌 token | 极高,典型 AI Slop |
| 迭代速度 | 慢,按天计 | 快,按小时计 | 快但质量不稳 |
| 可上线比例 | 高 | 高 | 低,常需人工修补 |
| 角色重心 | 工程师写代码 | 工程师拆需求 | 无明确角色 |
| 失败模式可追溯 | 高,Git 历史完整 | 高,spec.md 留痕 | 低,对话即丢失 |
| 学习曲线 | 传统 CS 基础 | 产品思维 + 提示工程 | 几乎为零 |
| 团队协作模型 | 集中式 PR 评审 | 契约对齐 + 异步评审 | 单兵,难以交接 |
取舍边界:Vibe Coding 适合需求清晰但人手紧张的小团队,以及需要快速验证 MVP 的早期产品;纯 AI 生成适合 demo 与一次性原型,但不可承担生产环境;传统开发依然适用于大型长寿命工程。读者在选型时应以"是否能在 24 小时内完成一次端到端迭代"作为分水岭。
观察 spec.md 的真正价值不是文档化,而是"反遗忘"。Claude Code 在长上下文中的指令遵循曲线是衰减的,把关键决策固化到文件里相当于给模型装上一个外部记忆。这个机制可以推广到所有"AI 协作工程"场景:从需求到部署、从设计到测试,凡是跨会话需要保留的事实都应该外化为文件,而不是依赖对话历史。一旦把"契约即对齐"内化为团队纪律,工程师的精力就能从"复述需求"释放到"编排工具链"上,这正是工程师角色翻转的物理基础。
数据 该工作流相比纯 AI 生成的最显著差异体现在可上线比例与 Lighthouse 分数上。基于流程化、契约化的拆分,产出的页面在性能分、品牌一致性、字段完整性三个维度的通过率均显著高于一次性 prompt 生成的产物。工程经验表明,引入 spec.md 后的页面,Lighthouse 性能分中位数提升约 15 到 25 分,品牌 token 覆盖率从约 30% 提升到 90% 以上,首版即可部署的比例从不到 40% 上升到 80% 左右。这三个数字共同表明,五步拆分带来的不是"AI 写得更努力",而是"约束被结构化地传递到了每一个决策点"。
五步工作流不是线性瀑布,而是一个以 spec.md 为轴心的反馈环。每一步的产物都被序列化进同一个契约文件,下一步的会话通过读取这份契约重新对齐意图,这种"文件即记忆、契约即对齐"的设计,让 Vibe Coding 从"AI 玩具"升级为可工程化的开发范式,也让工程师在零代码前提下,依然保留对最终产物质量与品牌一致性的完整掌控力。
第一步上: Grilling 会话捕获项目上下文
在五步工作流的全景里,第一步的任务是把"模糊念头"沉淀为"机器可消费的工程上下文"。这一步的入口不是让模型立刻读 README,也不是直接贴一份需求文档,而是发起一场结构化的 Grilling 会话------用一连串单刀直入的追问,把脑子里"想做投资人追踪应用"这种一句话需求,逼出技术栈、目标用户、模拟数据、MVP 边界四类硬信息。
触发方式:一句话说出想做什么
Grilling 会话的起点极轻。讲师把这一句开场称作"种子句",它只要求你描述"想做什么",不要求任何技术细节。常见的种子句范式有三类:业务驱动型 ------"我想做一个投资人追踪应用,记录 VC 偏好和会议纪要";产品驱动型 ------"我想做一个 SaaS 落地页,展示定价和功能";内容驱动型------"我想做一个个人博客,支持 Markdown 和 RSS"。种子句越具体,Grilling 会话第一轮追问的命中率越高。但即便只有"我想做个应用"五个字,Grilling Skill 也会兜底追问到目标用户这一层------这正是它区别于普通自由对话的关键。
问答节奏:一次只问一个问题

Grilling 会话刻意把节奏放慢:每轮只抛出一个问题,等回答落地后,再根据答案派生出下一轮子问题。这与"一次问十个问题"的多线程提问模式形成鲜明对比。多线程提问会让模型陷入"上下文过载",导致它优先回答最显眼的子问题、跳过边界条件;而单线程追问则逼迫模型在每轮对话里只聚焦一个决策维度,大幅提升回答的工程一致性。
这种节奏在 Claude Code 默认的 Plan mode 中表现尤为明显------Plan mode 本身就是"先想后做"的单线程工程范式。Grilling 会话相当于把这种范式前置到需求阶段,让产品上下文也吃到 Plan mode 的红利。详见 Claude Code 官方文档 中关于 Plan mode 的章节,以及 Slash Commands 文档 中关于 Skill 触发流程的说明。
常见追问维度:目标用户 / 模拟数据 / 技术栈 / MVP 边界
讲师把 Grilling 会话高频追问的维度归纳为以下四类。下表给出每类维度的追问目的、典型问题、以及缺失时的典型后果:
| 维度 | 追问目的 | 典型问题 | 缺失后果 |
|---|---|---|---|
| 目标用户 | 锁定使用场景与 UI 复杂度 | 这款应用给谁用?B2B 还是 B2C? | 落入通用 dashboard 范式,与所有竞品长得一样 |
| 模拟数据 | 提前定义 schema 与页面字段 | 有现成数据吗?字段长什么样? | Agent 自己编造数据,字段命名飘忽,接口对不齐 |
| 技术栈 | 锁定代码生成的语法与依赖 | 偏好 React/Next.js 还是 Vue/Svelte? | 模型在多个框架间漂移,反复 import 报错 |
| MVP 边界 | 控制首版范围,避免 feature creep | 这次只做登录 + 列表,可以吗? | Agent 一次性堆出 18 个页面,远超评审能力 |
目标用户追问的工程意义
目标用户维度看似和产品说明相关,实则直接决定后续 UI 范式选择。讲师以"投资人追踪应用"举例,指出面向个人早期投资人(VC scout)与面向基金合伙人(GP)的界面范式差异极大。Grilling 会话要求把目标用户具象化到一个角色(persona) ,例如"25-35 岁的早期 VC,每周看 50 份 pitch deck,需要 30 秒内判断是否跟进"。这种具象化直接转化为 shadcn/ui 组件库的选型与 Tailwind 主题色决策,详见 shadcn/ui 官方文档 与 Tailwind CSS 官方文档。
模拟数据维度对 schema-first 开发的支撑
Vibe Coding 的工程哲学里有一条隐含规则:先有数据形状,后有页面布局。Grilling 会话在第二轮左右一定会追问"用什么数据",并要求用户给出至少 3 条样例。这个要求看似烦琐,实则把后续 Prisma schema、TypeScript interface、API route 的定义路径全部锁死。讲师在课程示例中演示过:如果跳过这步,Agent 在写页面时会反复改字段名,导致前端组件 prop type 与后端返回类型长期不一致,这类 bug 在生产环境最难排查。
技术栈维度的取舍
| 方案 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Next.js + shadcn + Tailwind | 生态完整、Agent 训练语料多、Vercel 一键部署 | bundle 偏大 | 内容站、SaaS 落地页、电商 |
| Vite + React + 手写 CSS | 构建快、依赖轻 | 部署需额外配 Nginx/Vercel adapter | 内部工具、单页 demo |
| Astro + MDX | 静态优先、SEO 友好 | 交互组件需 island 架构 | 个人博客、文档站 |
讲师在课程中默认推荐 Next.js 路线,主要原因是 Next.js App Router 在 Claude Code 训练语料中出现频率最高,Agent 对其 API 行为的对齐度优于 Vite/Astro。Next.js 的官方约定式路由与 React Server Component 范式,在 Next.js 官方文档 中有完整说明。
MVP 边界:砍功能比加功能难
Grilling 会话最后一定会问"MVP 包含哪些功能"。这一步是产品经理最难回答、却对工程质量影响最大的环节。讲师反复强调:MVP 不是"做得少",而是"做得准"------每一个保留的功能都必须能用一句话描述清楚它的用户价值。
耐心价值:多答一轮可省后续多次重构
Grilling 会话看似把开发周期拉长(一轮问答平均耗时 3-5 分钟,完整 Grilling 通常 8-12 轮),但其回报率极高。讲师给出一个经验性结论:每多答一轮 Grilling 追问,可节省后续平均 2-3 次组件级重构。背后的机制是,Grilling 会话把"决策点"前置到对话窗口里;一旦模型进入代码生成阶段,修改一个 UI 字段名会牵动 React 组件、API route、Prisma schema、TypeScript interface 至少四个文件,而在前置问答里改一句话只需要 5 秒。
数据 讲师在课程示例项目中给出一组对比:同一款"投资人追踪应用",完成完整 10 轮 Grilling 会话的项目,在后续 Plan → Build → Review 闭环中触发组件重命名的次数为 2 次;而仅完成 3 轮 Grilling 就开始写代码的项目,触发重命名次数达到 11 次,且其中 4 次需要手动改 schema 迁移。重命名次数的差异,直接折算为 PR 评审时长与 token 消耗的差异------前者整体耗时约为后者的 38%。
本地安装:把 grilling-me Skill 装进项目 Claude Code
Grilling 会话的本质是一个 Claude Code Skill ------它是 Anthropic 官方推出的可复用提示词包,可在 Claude Code 概述文档 与 Slash Commands 文档 中查到 Skill 的加载机制与调用约定。安装步骤如下:
bash
# 1. 进入项目根目录
cd ~/projects/investor-tracker
# 2. 创建 .claude/skills 目录
mkdir -p .claude/skills
# 3. 把 grilling-me Skill 克隆到本地
git clone https://github.com/modelcontextprotocol/servers \
.claude/skills/grilling-me
# 4. 在 Claude Code 中调用
claude
> /skill grilling-me
安装完成后,Claude Code 在项目目录下会自动识别 .claude/skills/grilling-me/SKILL.md,并在用户首次发起"我想做一个 X"的需求时自动触发该 Skill。Skill 的设计目标是对开发者完全无感------不需要手动调用 slash command,Grilling 会话会在对话流中自然展开。
安装时的常见踩坑
- 路径大小写敏感 :
.claude与.Claude在 macOS HFS+ 上看似等价,但 Claude Code 只识别全小写.claude。建议在 git clone 后用ls -la二次确认目录名。 - Skill 文件命名 :Claude Code 通过
SKILL.md(全大写)识别 Skill 入口,误写成skill.md会导致 Skill 静默失效,无任何报错。 - 多 Skill 冲突 :如果项目下同时存在多个 Skill,Claude Code 会按文件名字母序匹配首个;
grilling-me与grilling-product同时存在时,后者会被优先加载。
Grilling vs 自由对话:边界条件对比
Grilling 会话与"直接和 Claude Code 自由对话"的取舍如下:
| 维度 | Grilling 会话 | 自由对话 |
|---|---|---|
| 触发方式 | 一句话种子句自动激活 Skill | 用户手动构造 prompt |
| 节奏控制 | 单线程,一问一答 | 多线程,可能一次性抛出多个需求 |
| 上下文结构 | 按"用户/数据/技术/MVP"四象限填充 | 线性堆叠,后期易丢失关键决策 |
| 适用阶段 | 项目从 0 到 1 的冷启动 | 项目已有明确 spec,只需局部修改 |
| 反模式 | 用 Grilling 会话修改单文件 bug | 用自由对话启动新项目 |
取舍原则:零基础启动项目必须走 Grilling 会话;项目已有明确 spec 文档时,Grilling 会话反而会拖慢节奏,此时直接进入 Plan mode 即可。
观察 Grilling 会话的本质,是把产品经理的"用户访谈"能力自动化。真实的产品经理在用户访谈中会做三件事:明确受访者画像、追问场景细节、划定需求边界。Grilling 会话把这三件事固化为 Skill 内的 if-then-else 分支,让模型在对话窗口内复现这套访谈流程。这条工程思路的启示是:任何"非代码"的软技能------用户访谈、需求评审、风险排查------都可以通过 Skill 机制沉淀为可复用的工程资产,这也是 Vibe Coding 把"工程师"角色从"写代码"翻转为"拆需求 + 编排工具"的核心抓手。完整的 Vibe Coding 工程哲学,可在该教程的零基础实操拆解中找到对应章节;配套的 MCP 协议说明参见 Model Context Protocol 官方文档 与 Anthropic MCP 官方介绍。
Grilling 会话是五步工作流中最轻的一步,也是后续四步能否对齐产品意图的承重墙。它不写一行代码,却决定了所有代码往哪个方向生长。
第一步下: Decisions.md 与 Spec.md 双文档契约
在 Vibe Coding 五步工作流的第一阶段,我们通过 Grilling 会话把脑子里那句"想做投资人追踪应用"的模糊念头,拆解成了技术栈、目标用户、模拟数据、MVP 边界四类硬信息。但 Grilling 本身只是"采访",真正能让这堆信息长期生效的,是结构化的沉淀。这一步的关键产物,是一对互补的工程契约:decisions.md 与 spec.md。前者是滚动日志,后者是蒸馏摘要;两者并用,才让五步工作流的第一阶段真正闭合。

为什么不是一份文档搞定
很多新手会直觉地想"我都已经问完了,直接整理成一份文档不就行了?"------这是 Vibe Coding 工作流里最常见的省事心态。问题在于,Grilling 会话里的每一条问答,在后续工程链路里承担的角色完全不同:有些问答是"为什么这么做"的决策过程,需要被未来翻看;有些问答是"最后到底怎么做"的最终结论,需要被所有下游 Agent 直接读取。强行合并,要么日志被结论稀释,要么结论被日志淹没,二者都不可取。
更致命的是,Grilling 通常不是一次性完成的。在第二步脚手架、第三步页面实现、第四步测试与第五步部署里,只要你回头改了主意、加了新约束、删掉了某条假设,Grilling 就会"再开一轮"。这时候如果只有一份文档,你就要么在结论文档里塞大量历史,要么回头翻日志找"我们当时是怎么决定的"。双文档契约正是为了切断这种混乱:让日志只管追加,让摘要只管当前态。
decisions.md:滚动黑匣子
decisions.md 是 Grilling 会话的全量日志,性质接近软件工程里的 Architecture Decision Record(ADR,架构决策记录)。它的工程角色有三个:
第一,保留决策上下文。每一条问答都要带"提问动机 + 备选答案 + 选择理由 + 反例假设"四要素。今天看似显而易见的"为什么用 Next.js 而不是 Nuxt",三个月后回看,如果不写下来,大概率会被自己忘掉;而一旦忘了,下一次迭代就会重蹈覆辙,在同一个坑里反复踩。
第二,对冲上下文窗口衰减 。Claude Code 这类 AI Agent 的有效上下文是有边界的------会话越长,早轮次的关键约束越容易被"挤出"模型注意力范围。一份外部化的 decisions.md,本质上等价于"给模型的长期记忆外挂",让 Agent 在每轮开始前先 cat decisions.md 把关键决策拉回当下窗口。这点在跨日开发、周末回来继续推进的场景里尤其关键。
第三,支持审计与回滚。当线上出问题、当新人接手、当你想 A/B 测试两条技术路线时,decisions.md 是唯一可信的决策时间线;没有它,任何"为什么当初这么选"的追问都会变成考古悬案。
spec.md:下游 Agent 的唯一入口
spec.md 是 decisions.md 的"蒸馏产物",是整个项目的 current state(当前态)摘要。它的工程角色恰好与 decisions.md 互补:
第一,单一入口原则。后续所有的 Skill------包括脚手架 Skill、页面实现 Skill、测试 Skill、部署 Skill------在启动时只允许读取 spec.md,不允许穿越到 decisions.md 里自己挑答案。这避免了"每个 Agent 自己从日志里挑了一份不同的 spec"导致的行为漂移,这种漂移在多 Skill 串联时会被指数级放大。
第二,明确 source of truth 边界。当 spec.md 与 decisions.md 出现冲突时,以 spec.md 为准;但 spec.md 必须在文件头部留一行注释,指向最新一次的回写时间与回写来源(可以是 Agent 自己的 commit hash),以便追溯。
第三,体积可控。spec.md 应当保持在一屏可读完的体量(经验值 200-400 行 Markdown),太长就说明它正在被 decisions.md 的细节污染,需要做一次反向蒸馏。
下面这张表用六个维度做 decisions.md vs spec.md 的对比与取舍,把两份文件的边界一次性说清楚:
| 维度 | decisions.md | spec.md |
|---|---|---|
| 工程角色 | 滚动日志 | 摘要契约 |
| 内容形态 | 每轮问答一条记录 | 合并后的最终结论 |
| 写入时机 | Grilling 全程追加 | 大改动后回写 |
| 读者 | 未来的自己 + 复盘 Agent | 所有下游 Agent |
| 体积趋势 | 单调递增 | 收敛稳定 |
| 冲突优先级 | 低(用于审计) | 高(source of truth) |
文件结构示例
下面是一段伪代码片段,演示两份文档在 Grilling 结束后的典型形态:
markdown
<!-- decisions.md 节选 -->
## 2025-XX-XX 轮 1
**Q: 目标用户是谁?**
A: 独立投资人 + 小型基金分析师,2 人内协作,日活 < 50。
备选:大型机构买方研究团队(否决,需要 SSO + 审计日志)。
理由:小团队最痛的是跨设备同步与导出。
## 2025-XX-XX 轮 2
**Q: 技术栈?**
A: Next.js (App Router) + Tailwind + shadcn/ui + 内存模拟数据。
备选:Remix(否决,生态不如 Next.js)、Nuxt(否决,团队不熟 Vue)。
markdown
<!-- spec.md 主体 -->
# 投资人追踪应用 --- 工程 Spec
> 上次回写: 2025-XX-XX(Grilling 轮 3)
> 数据来源: decisions.md 全部记录已收敛
## 1. 目标用户
独立投资人 + 小型基金分析师,2 人内协作,日活 < 50。
## 2. 技术栈
Next.js (App Router) + Tailwind + shadcn/ui + 内存模拟数据。
## 3. MVP 边界
仅做:标的列表、估值快照、笔记录入;
不做:实时行情、SSO、团队权限。
观察 从信息论角度看,decisions.md 与 spec.md 的关系,等价于"事件日志 + 状态快照":日志记录所有变更,快照记录当前态。任何分布式系统教科书都会告诉你,只保留日志会丢失读取效率,只保留快照会丢失回滚能力;两者并用,才能既快又稳。Vibe Coding 项目虽然工作单元是"一个 Agent + 一个工程师",但它在工程语义上等价于一个有多个写入者的协作系统,因此同样需要这套双轨。这也是为什么 Git 本身就是 log + snapshot 的双轨设计,本质上完全同构。
spec.md 是后续所有 Agent 的 source of truth
在五步工作流里,Spec 是唯一一个被 Step 2 之后所有步骤共同读取的文件。脚手架 Agent 读它来生成 create-next-app 的参数,页面 Agent 读它来枚举 Hero / Features / Pricing 三件套的内容,部署 Agent 读它来决定 Vercel 的环境变量命名。任何一条 spec 字段缺失或歧义,都会沿着调用链放大成"整页跑偏"。
这意味着 spec.md 必须做到三件事:字段唯一 (同一概念只允许一种命名)、数值明确 (不允许出现"大概""可能""之后再说")、边界清晰 (MVP 不做什么要单独成段)。参考 Claude Code 官方对 Plan Mode 的描述,Plan Mode 本身就是 Agent 在动手前先生成一份结构化方案,而 spec.md 正是 Plan Mode 输出的工程化沉淀,二者一脉相承。详见 Claude Code 文档 docs.anthropic.com/en/docs/cla... 与 Anthropic MCP 介绍 www.anthropic.com/news/model-...
维护技巧:大改动后立刻回写
spec.md 不是"Grilling 结束后的一次性产出",而是每次大改动后的同步快照。判断"是否大改动"的三个信号:
- 技术栈调整:从 Tailwind 换到 CSS Modules、或者新增 shadcn 之外的组件库。
- MVP 边界扩张或收缩:把"实时行情"从不做变成做,或者反过来。
- 数据模型变化:模拟数据从内存换成 SQLite,或者字段新增/删除。
只要命中其中任意一条,就要立刻追加一条 decisions.md 记录,并在 spec.md 头部刷新"上次回写时间"。这种"小步快跑"的同步策略,成本极低,但能把"半年后发现 spec 已经过时"的概率压到几乎为零。
数据 经验上,一份维护良好的 spec.md 通常在 200-400 行之间;超过 600 行时,几乎可以肯定它正在被日志细节污染,需要做一次"反向蒸馏"------把过于细节的内容从 spec 剥离回 decisions.md。如果一份 spec.md 不到 50 行,又大概率意味着 MVP 边界没收紧,后续 Agent 会在"猜你想要什么"上消耗大量 token 预算,导致总成本不降反升。
常见误区与踩坑清单
- 把 spec 当 README:spec.md 面向 Agent,README 面向人类访客;两者职责不能互相替代。
- 跳过 decisions 直接写 spec:会导致 spec 里出现"为什么"无法追溯,后续 Agent 在面对反例假设时无从判断。
- 每轮都重写 spec:浪费 token 且容易引入不一致;正确的做法是"大改动才回写"。
- spec 字段命名不一致 :比如同一概念叫
target_users又叫audience,会让所有下游 Agent 行为漂移。 - 把 secrets 写进 spec :spec 是要被 Git 入库的,任何 API key、token、邮箱密码都不能出现在里面,详见 GitHub Personal Access Token 文档 docs.github.com/en/authenti... 与 Vercel 文档 vercel.com/docs 中关于环境变量的章节。
把 Grilling 当成一场结构化采访,decisions.md 是这场采访的完整录像,spec.md 是录像剪出来的预告片。任何下游 Agent 只允许看预告片,只有人类工程师在审计或回溯时才去翻录像。理解了这层分工,五步工作流的第一步才算真正闭合;否则哪怕 Grilling 再细致,信息也会在第二轮脚手架之后就迅速失真,后面的四步只能反复救火。
第二步上: 挑选成熟产品作为克隆骨架
克隆不是抄袭,而是借骨架
"克隆一个成熟产品"这件事在工程师圈子里并不丢脸,但必须先把心结解开。一款用户量上百万的应用,它的列表页、信息密度、信息层级,都不是设计师坐在会议室里凭空拍脑袋拍出来的,而是被真实用户的点击、滚动、跳出、搜索行为反复打磨过的------成熟的布局等于成熟的心智模型。读者看到三栏就知道"左侧筛选、中间结果、右侧摘要是行业共识";看到列表卡片带涨跌色块,就会自动理解为"这是一个数字榜单";看到顶部 Tab 切换,就知道"这是有多个并列分类"。
借骨架与抄袭的边界,在于"借哪一层"。借的是布局节奏、信息层级、交互路径,这些属于"工程惯例",在 Next.js 文档里也能找到大量范例;不借的是品牌色、Logo、文案语气、配图风格,这些属于"商业资产"。一旦把这个边界划清楚,"我们要不要克隆 CoinMarketCap"这种问题就不会变成道德问题,而只是一个高效的工程起跑姿势。
两种克隆来源:日常使用的应用 vs Vercel 模板市场
克隆来源只有两条主路,各自适合不同场景。
第一条主路是你日常使用的应用 。如果你的目标用户是开发者,那你看 GitHub Trending、Product Hunt、Hacker News 的首页布局,就会发现"标题 + 简介 + 标签 + 跳转按钮 + 投票数"几乎是一个被证实有效的列表卡片范式。如果你要做的是投资人追踪,那你每天刷的 CoinMarketCap、Substack、The Information 都在教你怎么做"主体 + 关键指标 + 时间戳"三元组。你每天打开的应用,就是你的用户会打开的应用------这句话在 Vibe Coding 时代比以往任何时候都更真。
第二条主路是 Vercel 模板市场 (vercel.com/templates)。...%25E3%2580%2582%25E8%25BF%2599%25E6%259D%25A1%25E8%25B7%25AF%25E7%259A%2584%25E6%259C%25AC%25E8%25B4%25A8%25E6%2598%25AF%25E6%258A%258A%2522%25E5%25B7%25B2%25E7%259F%25A5%25E9%25AA%25A8%25E6%259E%25B6%2522%25E4%25BA%25A7%25E5%2593%2581%25E5%258C%2596%2C%25E9%2580%2582%25E5%2590%2588%2522%25E6%2588%2591%25E6%25B2%25A1%25E6%259C%2589%25E6%2598%258E%25E6%2598%25BE%25E5%2580%2599%25E9%2580%2589%2522%25E7%259A%2584%25E5%2585%259C%25E5%25BA%2595%25E5%259C%25BA%25E6%2599%25AF%25E3%2580%2582%25E6%25A8%25A1%25E6%259D%25BF%25E7%259A%2584%25E4%25BC%2598%25E5%258A%25BF%25E6%2598%25AF%25E5%25B7%25B2%25E7%25BB%258F%25E5%25AE%258C%25E6%2588%2590%25E4%25BA%2586%25E9%2583%25A8%25E7%25BD%25B2%25E4%25BC%2598%25E5%258C%2596%25E3%2580%2581SEO "https://vercel.com/templates)%E3%80%82%E8%BF%99%E6%9D%A1%E8%B7%AF%E7%9A%84%E6%9C%AC%E8%B4%A8%E6%98%AF%E6%8A%8A%22%E5%B7%B2%E7%9F%A5%E9%AA%A8%E6%9E%B6%22%E4%BA%A7%E5%93%81%E5%8C%96,%E9%80%82%E5%90%88%22%E6%88%91%E6%B2%A1%E6%9C%89%E6%98%8E%E6%98%BE%E5%80%99%E9%80%89%22%E7%9A%84%E5%85%9C%E5%BA%95%E5%9C%BA%E6%99%AF%E3%80%82%E6%A8%A1%E6%9D%BF%E7%9A%84%E4%BC%98%E5%8A%BF%E6%98%AF%E5%B7%B2%E7%BB%8F%E5%AE%8C%E6%88%90%E4%BA%86%E9%83%A8%E7%BD%B2%E4%BC%98%E5%8C%96%E3%80%81SEO") 元数据、响应式断点这些工程细节,这些"脏活"在 Tailwind CSS 官方文档 与 Next.js 部署文档 里也能找到对应实现;缺陷是"它为通用场景设计,不一定贴合你的垂直业务"。
挑选标准:列表页 + 详情页的双视图齐备
挑骨架不能凭感觉,需要一张硬清单。最硬的一条是:你选的目标应用,必须同时具备"列表页"和"详情页"两种视图,且这两种视图之间有清晰的跳转路径。原因是 MVP 阶段几乎所有应用都逃不掉"列表 + 详情"这条主链路:列表页负责"扫一眼全局",详情页负责"看一个具体对象",两者缺一,都意味着你的应用本质上是单视图工具,无法满足"扫 + 看"的用户习惯。
第二条标准是"视觉节奏可截图可标注"。如果你打开一个候选应用,脑子里浮现不出"我能不能用三张截图讲清它的全部布局节奏",那它就不是一个合适的克隆对象------说明它的视觉密度过高或过低,信息架构对你来说不友好。
第三条标准是"核心交互路径 ≤ 3 步"。从首页到完成一次核心操作(比如"加入追踪""收藏""筛选"),不应该超过三次跳转。超过三次意味着目标产品的复杂度不适合 MVP 阶段直接克隆。
| 维度 | 日常应用 (CoinMarketCap 类) | Vercel 模板 |
|---|---|---|
| 业务贴合度 | 高 (你熟悉的目标场景) | 低 (通用模板) |
| 视觉密度 | 高 (信息密集,需要取舍) | 中 (结构清晰但留白偏多) |
| 部署成本 | 高 (需重新实现状态、SEO、缓存) | 低 (一键部署) |
| 二次定制成本 | 中 (改结构容易,改色板难) | 高 (改结构难,改色板容易) |
| 最适合的阶段 | 已知垂直业务、需要快速对齐心智 | 完全没想好要做什么、先要一个能跑的壳 |
用 CoinMarketCap 举例:三栏布局迁移到影响力者追踪
CoinMarketCap 是一个被低估的"骨架教学样本"。它的列表页采用经典三栏:左侧是"过滤器面板"------市值范围、类别标签、交易所筛选;中间是"加密货币榜单"------带涨跌色块、24h 成交量、市值排名的卡片;右侧是"摘要面板"------头部资产的价格快照和市场动态。这种节奏在 SaaS 与数据型应用里其实随处可见,不是 CoinMarketCap 的发明,而是它把这种结构推向了极致。
这套三栏节奏可以零成本迁移到一个完全不同的垂直:追踪影响力者(KOL/Investor Tracker)。左侧过滤器换成"行业、地区、粉丝量级、平台来源";中间榜单换成"KOL 列表,带订阅增长率、内容互动率、平均曝光量";右侧摘要换成"本周头条 KOL 的最近发言摘要 + 相关项目涨跌"。你看,布局节奏没变一个像素,但承载的业务语义完全换了一套。
更妙的是,这种迁移保留了"用户已经被训练出的肌肉记忆"。一个习惯刷 CoinMarketCap 的投资人,看到你的 KOL 追踪器三栏布局,会瞬间知道"左边筛、中间看、右边扫",零学习成本------这种零学习成本,在 MVP 阶段比任何花哨动效都值钱。
时机判断:什么时候退回 Vercel 模板
日常应用克隆不是万能解。下面三种情况出现任意一种,就该退回 Vercel 模板市场兜底:
- 当下没有明显候选:如果你的目标用户在脑中还是一片模糊,你无法说出"我的用户每天打开 X 应用",那就不该硬克隆,否则你克隆到的只是"看起来像"的反模式。
- 场景过于垂直且没有现成对标:比如"链上 DeFi 收益聚合器",专业到只有不到一千人用,这种情况下没有人替你打磨过视觉节奏,克隆只会克隆到一堆"看起来对、用起来错"的细节。
- MVP 第一周目标只是"先有一个能跑的壳":如果连业务都还没验证,先别从成熟产品借骨,先从模板借壳更划算。
这三条边界一旦画清楚,你就不会陷入"找克隆对象找了三天的内耗"------Vibe Coding 的最大浪费不是 AI 写错代码,而是人原地打转。
动手前先截图:锁定要复用的视觉重点
挑好骨架之后,动手写代码之前还有一道必经工序------截图。不是为了留档,而是为了"锁定要复用的视觉重点"。打开你想克隆的应用,按这个清单截图:
bash
# 项目资产目录结构示例
mkdir -p assets/reference
cd assets/reference
# 克隆目标截图命名规范 (把截图丢进 assets/reference/)
# home.png 首页全貌 (确认主色、辅色、几栏几行)
# list.png 列表页全貌 (信息密度与卡片组件结构)
# detail.png 详情页全貌 (字段布局与元数据位置)
# filter-open.png 筛选打开后的中间状态 (交互路径的关键帧)
# flow-*.png 一次完整核心交互的若干关键中间态
把截图丢进 assets/reference/ 目录,文件名按页面命名,后面让 Claude Code 解析截图需求时,这些文件就是"视觉契约"。配合 Claude Code 官方文档 里提到的工作流,你可以直接让 Agent 把这些截图作为参考输入,反过来约束 layout 决策。
这一步十分钟换三小时------Vibe Coding 时代最大的浪费,不是写错代码,而是写到一半才发现"原来首页不该放 Logo 占那么大"。
观察 这一步的核心不是"模仿谁",而是"训练自己的视觉肌肉"。你每克隆一个成熟产品的骨架,都会偷师到它的信息层级决策:为什么 CoinMarketCap 把"涨跌幅"放第二行而不是第一行?为什么 Substack 把"作者头像"放标题旁边而不是右侧?这些决策背后都是真实用户行为的收敛值。克隆的本质不是抄答案,而是抄"出题思路",把决策依据偷过来。
数据 一个粗略但能用的经验数字是:克隆成熟产品比从零设计节省 60%-80% 的"决策时间",但仅节省 10%-20% 的"实现时间"。这意味着克隆的最大价值,集中在前端的"想清楚"环节,而非"写出来"环节。Vibe Coding 时代,这 60%-80% 的"想清楚"时间,会被工具进一步压缩,但前提是你已经"想清楚"------而所谓想清楚,正是这一步里你从成熟产品骨架里偷师到的东西。

第二步下: Deep Research Skill 识别可复用组件
在 Claude Code 的能力图谱里,Deep Research 是一项默认装载的设计调研技能。它并不像插件市场里那些需要手动安装的 extension,而是与 Slash Commands、Plan mode、Review mode 一样,在安装完 Claude Code 之后就可以直接调用。可以把它理解成 Agent 内置的一个"反向工程浏览器"------给定一个站点地址,它会代替人去完成原本需要手动打开 DevTools、扒 Network 面板、查 HTML 源码、再去 GitHub 搜索类似实现这一整套动作。整套调研流程从触发到落盘,通常只需要几分钟,这是手工方式无法企及的速度。
触发方式非常朴素。打开一个新的 Claude Code 会话,把目标站点的首页 URL 直接粘贴进对话框,Agent 便会自主发起调研。它会沿着首页的链接图向下爬取若干层,把页面里出现的 CSS 类名前缀、JS 资源 hash、可访问的样式表、图标字体声明都收进上下文,再与已知开源组件的特征库做比对。最终输出的并不是一段阅读笔记,而是一份可以直接进入工程评审的清单。整个过程不需要用户额外编写 prompt 模板,这是 Deep Research 与一般网页摘要工具的核心差异。

典型产出会落在三个维度。第一是站点使用的 UI 库,例如检出 shadcn/ui、Radix UI、Mantine、Chakra、Material UI 等组件库的痕迹;第二是开源组件清单,即页面里那些看起来像是自研、但其实在 npm 上已经有现成实现的卡片、表单、模态框、Tab 切换、轮播图;第三是工程惯例,例如用了什么 CSS 方案(Tailwind / CSS Modules / vanilla-extract)、状态管理方案(Redux / Zustand / Jotai)、动画方案(Framer Motion / GSAP / Motion One)。这三类信息组合在一起,基本能还原一个站点 80% 左右的前端骨架,足以支撑下一步的 v1 合并。
工程价值落在"避免重造轮子"五个字上。组件复用不仅意味着少写代码,更重要的是合规与稳定。开源组件往往经过数千次 commit、上百个 issue 的打磨,在可访问性(a11y)、键盘导航、屏幕阅读器兼容这些细节上都有现成的兜底;而手写一个看似简单的 Dropdown Menu,常常会忽略 ARIA 属性、焦点陷阱、Esc 关闭、点击外部关闭等边界条件。复用即合规,复用即稳定,这两件事在产品上线阶段比"性能再快 5%"要重要得多,尤其是在面对合规审计与无障碍法规时,复用社区已审过的组件几乎是唯一的低成本路径。
把这份清单交接给下一步的方式也很直接:把 Deep Research 输出的 Markdown 报告原样带进 v1 合并阶段。Claude Code 在进入"合并多个候选站点方案"的会话时,会自动读取上下文里已有的组件清单,作为构建新骨架时的零件库。Agent 会优先从清单中挑选最匹配的现成组件,而不是凭直觉去 npm 上随机搜索;同时,清单中的版本号、依赖关系、潜在冲突点都会被一并带过去,避免在 v1 阶段出现"装上跑不起来"的尴尬。
观察 这一步实际上把前端选型自动化成了一次调研任务。传统流程里,前端 Lead 要花半天到一天翻 DevTools、找替代品、写选型文档;现在 Agent 一次会话就能给出可执行清单,人力从"执行选型"被上移到"评审清单"。工程师的注意力被释放到"这个组件是否符合品牌气质""这套交互是否符合目标用户心智"这些无法自动化的问题上,这是 Agent 时代工程师角色翻转的典型缩影。
数据 在一次典型调研里,Deep Research 通常会输出 20 到 40 个候选组件,覆盖导航、表单、反馈、数据展示、布局五大类。清单中大约 70% 的条目能在公开 npm 包里找到直接可用的实现,剩余 30% 才需要二次封装或局部自研。这意味着 v1 阶段的可复用率往往超过 60%,显著降低了从零起步的边际成本,也让原本一周起步的前端搭建压缩到一两天内即可完成初稿。
下面这段伪代码展示了如何在一个新会话里触发 Deep Research 并把产物落盘,作为 v1 合并阶段的输入:
bash
# 在 Claude Code 新会话中触发 Deep Research
claude chat --new-session <<'EOF'
请对 https://example.com 做深度设计调研,输出 Markdown 格式的组件清单,
维度包括:UI 库、开源组件、CSS / 状态管理 / 动画方案。
请尽量给出每个候选组件对应的 npm 包名与最低可用版本。
EOF
# 把会话产物落盘,供 v1 阶段直接读取
claude export --last-session > research-report.md
接下来是一张常见的输出对照表,展示了 Deep Research 在不同类型站点上的识别表现与可复用率:
| 维度 | 典型识别项 | 可复用比例 | 主要工具 |
|---|---|---|---|
| UI 库 | shadcn/ui、Radix、Chakra | 90%+ | shadcn CLI、Radix Themes |
| 通用组件 | Dropdown、Modal、Tab | 70-80% | Radix Primitives、Headless UI |
| CSS 方案 | Tailwind utility class | 几乎 100% | Tailwind CSS |
| 动画方案 | Framer Motion / Motion One | 80% | Framer Motion |
| 状态管理 | Zustand / Jotai | 70% | Zustand |
下面是一份关于"复用 vs 自研"的取舍矩阵,这几乎是每个前端团队在 v1 阶段都会反复讨论的经典问题。表中把两种路线在五个维度上做了显式对比,便于在评审会上快速对齐决策:
| 取舍维度 | 复用开源组件 | 全自研组件 |
|---|---|---|
| 上线速度 | 快,几小时内接入 | 慢,通常需要数周 |
| 可访问性兜底 | 现成,经过社区验证 | 需自行测试与审计 |
| 品牌差异化 | 弱,容易"撞脸" | 强,可完全定制 |
| 长期维护成本 | 跟随上游版本升级 | 内部可控,但需投入人力 |
| 适用阶段 | v1 MVP、验证期 | v2+、品牌成熟期 |
取舍的核心在于阶段。在 v1 阶段,业务目标是用最小成本验证核心假设,复用能换速度;到了 v2 之后,品牌差异化与设计语言沉淀变得更重要,才开始考虑局部自研或对开源组件做深度二次定制。把这条原则写在团队的选型 SOP 里,可以避免无意义的反复争论。
官方文档里关于 Claude Code 的 Deep Research 默认行为可参考 docs.anthropic.com/en/docs/cla... 与 docs.anthropic.com/en/docs/cla... Agent 在拿到 URL 时会执行的步骤与可配置的输出格式。如果想把组件清单进一步结构化以便后续 Agent 解析,Model Context Protocol 官方文档 modelcontextprotocol.io/ 描述了如何把"调研输出"封装成可被下游 Agent 读取的结构化资源;GitHub MCP Server 仓库 github.com/modelcontex... 则给出了一组可立刻复用的工具实现,例如把"已识别的组件清单"作为仓库 issue 模板直接提交,从而让清单从一份文档升级为可编排的资源。
需要警惕的是,Deep Research 并不是万能的。它的识别依赖于站点本身没有做重度混淆(minified class names、随机 hash、SSR + hydration 后才注入的 DOM),对于那些刻意隐藏技术栈的站点,识别率会显著下降,甚至可能给出错误结论。此外,识别出的组件库版本可能滞后于最新发布,引入时务必通过 npm view <pkg> versions 或 GitHub releases 复核一次,避免把 deprecated API 带进新工程。同时也要注意版权与商标风险:借鉴视觉语言是常规做法,但逐像素复刻 logo 与品牌色块则属于另一回事,清单里如果出现品牌资产,务必在 v1 合并阶段做替换。
把这一步放在克隆流程里的意义,在于把"我看到一个好用的设计"翻译成"我拿到了一份可执行的零件清单"。下游 v1 合并阶段只需要做减法和组合,不再从零做加法,这是用 Agent 替代重复劳动的最直接体现。借骨架这件事,从此有了可复制、可审计、可交接的工程语义。
第三步: Spec 驱动的 Clone 改造工程
第三步:Spec 驱动的 Clone 改造工程
Spec-Driven Development(规格驱动开发)的核心思路非常朴素:不再把「自然语言需求」当成聊天式的提示词丢给 Agent,而是先把它落成一份结构化的 spec.md,再把这篇 Markdown 当成 Agent 的「输入契约」喂进去。这样做的工程价值在于,所有改造动作都可以回溯到 spec.md 中的具体字段------一旦 UI 文案、列名、详情页结构需要回滚,工程师不必重新叙述上下文,只需改 spec,再让 Agent 跑一遍相同的改造指令。

为什么把 spec.md 当成 Agent 的输入
在传统 prompt 工程里,我们习惯把需求写成「请把首页的标题改成 XX,把三张卡片改成 XX」这样的句子。这对一次性 demo 没毛病,但一旦要 clone 一个完整的站点并在此基础上做二次改造,这种零散对话会迅速耗尽 Claude Code 的上下文窗口,也会让 Agent 在第三轮、第四轮之后开始「幻觉字段」------比如它会臆造 spec 里没有的列,或者把已经约定好的字段悄悄改掉。spec.md 的作用就是把「单一事实来源」(single source of truth)从对话流中剥离出来,放进 Agent 的 file system 工具调用范围里------Claude Code 会主动用 Read 工具读它,而不是依赖对话记忆。Claude Code 的官方文档(见 docs.anthropic.com/en/docs/cla... )把这种「喂文件优于喂句子」的工作流列为推荐范式之一。
这份 spec.md 通常包含三块内容:
- 数据契约 (Data Contract):表名、字段名、字段类型、可选枚举。例如
articles.title: string、articles.published_at: ISO8601。 - 视图契约 (View Contract):每个路由对应的页面组件名、关键文案占位符、列表项字段映射。例如
/blog/[slug]路由对应BlogDetailPage组件,需要绑定title / author / cover / body四个字段。 - 改造禁区(Preservation Boundary):明确告诉 Agent,clone 来的 Tailwind class、shadcn 组件、版式布局不许动,只许动数据绑定层。
改造动作清单
把 spec.md 喂给 Agent 之后,Claude Code 会按 spec 走完一整套改造流水线,大致落成以下四类原子动作:
- 重命名列名 :把 clone 源里的硬编码字段(比如
header_text、body_html、create_time)映射到 spec 里的语义化字段(比如title、content、published_at)。这一步直接落到 TypeScript 类型定义与所有引用点。 - 改文案 :把 clone 源里的占位文案(
Lorem ipsum、Hello World、Sample Article 1)替换成 spec 里指定的业务文案。文案本身可能横跨 5 到 20 个组件,Agent 会借助grep与ripgrep等搜索工具批量替换。 - 替换模拟数据 :把 clone 源里写死在组件内的 mock 数组,改成从
lib/data/*.ts读出来的真实结构。这是从「写在 JSX 里」到「数据驱动」的范式跳跃。 - 重建详情页:clone 源常常只有列表页骨架,详情页要么是死链要么是占位符。spec 给出详情页字段之后,Agent 会基于现有列表项布局派生详情页骨架,补上动态路由。
这四类动作的顺序在 spec 里也应当写明,因为它们之间存在依赖------先重命名列名,再替换模拟数据,最后才重建详情页。如果顺序颠倒,Agent 会陷入大量「找不到字段」的错误回环,白白消耗 token budget。
保留原则:不动 UI 组件与版式
这一步是整套工程里最容易翻车的点。Spec-Driven 不等于 Spec 支配一切。clone 源之所以值得 clone,是因为它的视觉密度、交互细节、栅格系统已经被原作者调过一遍------把这些当作「免费的设计资源」才是 Vibe Coding 的核心杠杆。所以 spec.md 里必须显式划定一个保留边界,告诉 Agent:
- 不许改
components/ui/*下任何 shadcn 组件的 props 与样式 - 不许改
tailwind.config.ts里的 theme 扩展 - 不许改
app/layout.tsx里的全局结构 - 只允许改
app/**/page.tsx与lib/**下的业务逻辑层
这种「组件不动、版式不动、只动数据层」的边界条件,本质上是一种单向数据流约束:UI 是 clone 来的固定面,数据是 spec 注入的变量面,二者在 page.tsx 这一个文件里完成对接。这样即使后续 spec 再迭代 v2、v3,UI 层都不用重做。
工程产物:web-1.0 目录
跑完 Spec 驱动的改造流水线之后,项目根目录下会出现一个 web-1.0 目录。这是 Vibe Coding 工作流里一个很有意思的工程惯例------它不是「最终产品」,而是「第一个可演示版本」的快照。所有后续的迭代都从这个目录派生:v1.1、v2.0 各自一个目录,互不污染。这种「按版本切片」的目录组织方式,在多轮 Spec 迭代时能避免 Agent 把 v2 的改动回灌到 v1。
进入 web-1.0 目录之后,执行以下命令即可在本地浏览器看到改造后的成品:
bash
cd web-1.0
npm install
npm run dev
# 默认监听 http://localhost:3000
打开浏览器访问 http://localhost:3000,你会看到 UI 完全是 clone 源的样式,但所有文案、列表项、详情页都已经按 spec 替换完毕。这是「视觉继承 + 数据替换」的一次完整演示。Next.js 的 App Router(详见 nextjs.org/docs )在这一步会自动接管热重载,改一行 spec 再让 Agent 跑一遍,浏览器秒级刷新。
执行环境:新开 Claude Code 会话
这一步在工程上看起来像小事,但实操里极其关键:跑 Spec 驱动的改造,务必新开一个 Claude Code 会话,不要在已经跑完 Deep Research 调研的同一个会话里继续。原因有三:
- 上下文污染 :Deep Research 会话里塞满了站点扒取的 HTML 片段、Network 请求记录、相似实现的搜索结果,这些信息会干扰 Agent 对
spec.md的注意力。Claude Code 的上下文窗口虽然大,但「信噪比」比「绝对长度」更重要。 - 工具白名单 :Deep Research 会话默认激活了
WebFetch、WebSearch这类联网工具,而 spec 改造只需要Read、Write、Edit、Grep、Glob这五个文件操作工具。在新会话里把工具范围收敛,Agent 就不会跑去重新联网扒数据,改造动作会更聚焦。 - 可重放性 :把「调研」与「改造」拆到两个会话里,意味着每一步都是可重放的。如果改造跑挂了,可以重开一个新会话,从头喂同一份
spec.md,得到一份几乎一致的产出;而混合会话里如果挂掉,debug 起来非常困难------你分不清是调研的产物还是改造的产物出了问题。
具体的操作是:在终端里执行 claude 命令新开会话,然后用 @spec.md 这样的语法把规格文件当作首条用户消息喂进去。Claude Code 会自动把 spec 内容解析成改造任务清单,然后按顺序执行。Plan mode 会在动手前先把任务清单打印到终端让工程师确认,这正好可以作为 Spec-Driven 工作流的「预演」环节。
对比矩阵:clone 原貌 vs v1 重命名 vs spec 字段
为了更直观地展示 Spec 驱动改造前后的差异,这里用一个虚构的「博客列表 + 详情页」场景做对比:
| 维度 | Clone 原貌 | v1 重命名后 | Spec 字段(契约) |
|---|---|---|---|
| 数据来源 | 写死在 page.tsx 内的 mock 数组 |
抽离到 lib/data/articles.ts |
spec.md 第 3.1 节 articles 表 |
| 列名字段 | header_text、body_html、create_time |
title、content、published_at |
严格匹配,不允许别名 |
| 文案 | Sample Article 1 / Lorem ipsum dolor |
Vibe Coding 入门 / 真实摘要 |
spec.md 第 4.2 节文案池 |
| 列表项 UI | clone 源卡片样式 | 不动 | 不在 spec 范围内,沿用 clone |
| 详情页 | 死链 /blog/sample-1,渲染 not found |
动态路由 /blog/[slug],渲染真实字段 |
spec.md 第 5 节详情页契约 |
| TypeScript 类型 | 无 | interface Article { ... } |
spec.md 附录 A 数据字典 |
| 测试覆盖 | 无 | Vitest 单测 + Playwright E2E | spec.md 第 6 节验收清单 |
方案 A(直接改源) vs 方案 B(Spec 驱动) 的取舍在于:方案 A 适合一次性 demo 与快速实验,改动一行就生效,但无法回滚、无法审计,迭代到第三轮时基本失控;方案 B 适合需要交付给团队、需要在多轮迭代里保持一致性的项目,代价是前期需要花时间写 spec.md,以及每个版本都会留下完整的 spec 历史快照。Vibe Coding 的工程实践证明,只要 spec 的迭代速度跟得上产品迭代速度,方案 B 的长期收益显著高于方案 A。
常见踩坑清单
把这套 Spec 驱动的 clone 改造在生产里跑过几轮之后,有几个坑是反复出现的,提前列在这里供对照:
- spec 里出现别名:spec 写「标题也叫 headline」,Agent 会随机挑一个用。规范做法是 spec 只允许出现 canonical name,别名放附录,改造时统一收敛到 canonical。
- clone 源里有内联样式 :Tailwind class 不动,但有些 clone 源会把颜色直接写进
style={{ color: '#fff' }},这不在保留边界里,Agent 会以为是 spec 要求,误删。需要 spec 里显式列出「保留所有内联 style 属性」。 - 详情页字段缺失:clone 源只有列表项,没有详情页字段,Agent 会默认补全字段,但补出来的内容很可能是幻觉。规范做法是 spec 里明确写「若 spec 未声明,字段值取空字符串或 null,不得臆造」。
- shadcn 组件版本漂移 :clone 源用的是 shadcn 0.4,本地
npx shadcn@latest add装的是 0.8,组件 API 已经变了。需要在 spec 里锁版本,或者干脆用npx shadcn@0.4 add这种带版本号的安装命令。
观察 把 spec.md 当成 Agent 的输入契约,本质上是一种「上下文外部化」的设计模式------所有业务约定都不再依赖对话记忆,而是落到 file system 里由 Agent 主动读取。这种模式让 Vibe Coding 从「一次性 prompt 工程」升级为「可重放、可审计、可回滚的工程流程」。同时,严格划定 UI 保留边界,让 clone 源的设计资产可以被反复复用,而不是被每轮 spec 迭代覆盖掉。在团队协作场景下,spec.md 还能直接成为 PR review 的对账清单------reviewer 不必逐行看 diff,只需核对 diff 是否与 spec 变更一致。
数据 实操经验上,一份中等复杂度的 spec.md(覆盖 1 个数据表、5 个页面、约 30 个文案字段)大约 300 到 600 行 Markdown。Claude Code 在新会话里跑完整套改造,通常消耗 40k 到 80k tokens,耗时 8 到 18 分钟。产出的 web-1.0 目录包含 25 到 50 个文件,首次 npm install 后 npm run dev 启动时间 2 到 4 秒。这个量级足以让零基础工程师在单次会话里完成一个可上线页面的 Vibe Coding 全流程。后续的 v1.1、v2.0 迭代会沿用同一份 spec.md 的增量版本,Agent 只需读取 diff 部分,无需重新理解全量上下文。这正是 Spec-Driven 在多轮 Vibe Coding 迭代里最大的杠杆点。
第四步上: Impeccable Skill 的四阶段设计哲学
把"设计规范"装进 Claude Code 的 Skill 系统,是这套零基础 Vibe Coding 流程的第四步核心动作。Impeccable 是一个在 GitHub 上开源的设计类 Skill 仓库(下文给出官方文档入口),它的作者把 Anthropic 提出的"Skill 机制"用在前端场景:把原本散落在 Figma、品牌手册、Confluence 页面里的设计原则、颜色规范、排版约束、组件风格,打包成可被 Agent 自动加载的"前人经验包"。对于零基础用户来说,直接调用它,等于让 Agent 在一晚上学会了顶级前端工程师的设计直觉,而不需要自己去啃 50 页设计手册,也不需要懂什么叫做"视觉层级"或"信息密度"。这是 Skill 化设计系统相对于传统设计文档的范式跃迁:规范不再是被阅读的资料,而是被执行的行为。

Impeccable 内部把一次完整的设计打磨流程拆成四个阶段:Start / Iterate / Polish / Maintain。每个阶段都对应着一组子技能(Sub-skill),用来解决设计-开发链路里的不同问题。
| 阶段 | 子技能定位 | 典型触发时机 | 对应 Agent 行为 |
|---|---|---|---|
| Start | 从零规划视觉风格 | 仓库还没有任何 UI 文件 | 拉取设计 token、生成 baseline 主题 |
| Iterate | 在已有 UI 上小步迭代 | 已经能看到页面但还在调味道 | 局部修改间距、字号、圆角、阴影 |
| Polish | 扫尾级精修 | UI 已经能跑,但细节有 AI 痕迹 | 调用 Detector 自动清理 prompt 残留 |
| Maintain | 长期一致性维护 | 后续每次新增页面 | 在 Agent 写入 UI 前自动应用规范 |
四个阶段不是简单的串行队列,而是一个有状态机意味的 DAG(有向无环图) 。Start 是入口节点,只在项目最冷启动时跑一次;Iterate 是日常工作节点,占用时间最长,因为产品需求会反复变化;Polish 是里程碑节点,每次大版本发布或上线前必须扫一遍;Maintain 是常驻节点,每次文件写入都会被触发,几乎不消耗额外 token。新手最容易犯的错,是把 Start 误当成"一次性动作",于是每次新建页面都从头跑------这会浪费大量 token,还会让 Agent 反复覆盖已有规范。正确做法是把 Start 的产出固化成 baseline 主题文件(比如 theme.ts 或 tailwind.config.ts),后续所有阶段都基于它来增量修改。
在这个具体场景里,UI 已经被 Spec 驱动生成出来了------Hero、Features、Pricing、Contact、FAQ 五件套都已经渲染到本地 http://localhost:3000,可以被浏览器直接访问。所以正确的做法不是从 Start 跑一遍(那是浪费 token 的重复劳动),而是直接跳到 Polish + Maintain 组合。Polish 负责"扫干净"------清除掉那些一眼能看出是 AI 写的痕迹;Maintain 负责"立规矩"------保证下次让 Agent 加新页面时,它依旧会遵循同一套设计语言。这两步一前一后,正好对应"修旧"与"立新"两个动作。如果只用 Polish 而忽略 Maintain,后续每次新增组件都会重新引入 AI 痕迹;如果只用 Maintain 而跳过 Polish,当前页面的味道就始终带着"机器味"。
Detector 子机制 是 Impeccable 里最容易被低估的设计。Detector 不会修改产品功能,只关心"非功能性的语言残留"。它的工作流大致如下:
bash
# 触发 Detector 子技能的伪代码示意
detect_ai_artifacts() {
patterns=(
"Certainly!"
"Here is the code"
"I hope this helps"
"Let me explain"
"作为一名 AI"
"🌟|✨|🚀"
)
for file in $(git diff --name-only -- '*.tsx' '*.jsx' '*.css'); do
matches=$(grep -nE "${patterns[*]}" "$file" || true)
if [ -n "$matches" ]; then
sed -i -E "s/${patterns[*]}//g" "$file"
echo "Cleaned: $file"
fi
done
}
上述脚本并非 Impeccable 仓库里真实存在的 Shell,而是把它的工作机制翻译成可读伪代码:每次 Agent 写入 UI 文件之后(无论是手写还是 Skills 调用),Detector 会扫描 git diff 输出,把"Certainly!"/"Here is the code"/"作为一名 AI"/装饰性 emoji 这些人类一眼能识别为"AI 味"的语料删干净,再把文件写回工作区。这样做的工程意义在于:很多零基础用户其实分不清"代码能不能跑"和"代码读起来像不像专业工程师写的",Detector 替他们补上了这道鸿沟。从 token 经济的角度看,Detector 把"扫尾质量"这一原本需要在 prompt 里反复强调的指令固化成了自动化动作,Agent 的 system prompt 因此可以保持精简,不必每次都重复"请不要写 Certainly!"这种弱指令。
不过,Detector 不是万能的。它在对比 "AI 写作腔 vs 人写" 时仍然会出现两种典型的取舍:
| 取舍维度 | Detector 自动化清理 | 人工 review 兜底 |
|---|---|---|
| 速度 | 毫秒级,跟随每次写入 | 至少数十分钟 |
| 覆盖率 | 仅命中内置正则字典 | 可识别上下文语义错误 |
| 误伤率 | 偶发删掉合理英文短语 | 几乎为零 |
| 上下文理解 | 完全无 | 有 |
换句话说,Detector 更像"自动 Lint 工具",而不是"语义审稿人"。把它放在 Polish 阶段是合理的;但上线前的最终 review 还是得靠人(或者用另一个 Agent,例如 Sonnet 模型,做对照阅读)。这也是为什么 Impeccable 推荐 Polish 之后再人工 review 一遍,而不是把 Detector 当成唯一把关人。
在实际操作中,这套流程鼓励一种反直觉的习惯------先问 Agent,再选 Skill 。很多零基础用户习惯直接 claude "/impeccable.start",这是低效的:Agent 此时并不知道仓库当前长什么样,只能盲跑全量子技能。正确做法是先让 Agent 跑一次侦察:
python
# 让 Agent 自检当前 UI 状态
state = agent.scan(
target_dir="app/components",
look_for=[
"已落地的页面数量",
"是否残留 AI prompt 痕迹",
"设计 token 是否统一",
"可访问性(a11y)基线",
],
)
recommend_skills = agent.recommend(state)
# 输出示例:
# - /impeccable.polish (高优先级,扫尾)
# - /impeccable.maintain (中优先级,锁规范)
# - /impeccable.iterate (低优先级,等用户新需求)
print(recommend_skills)
这段伪代码描绘的交互模式是:Agent 根据当前仓库状态(scan 的输出),反向推荐要加载的子技能组合(recommend)。这相当于把"工程师主动选工具"翻转成"工具主动适配工程现场",是 Vibe Coding 强调的"低上下文也能产出"的典型落地。在 token 预算紧张时,这种"按需加载"比"全部加载"省下 50%-80% 的 prompt 长度,因为 Agent 只需要拿到当前阶段真正需要的那几个子技能定义,不必把四阶段文档一次性塞进上下文。
观察 Impeccable 真正的工程价值,不是它列出了多少条设计规则,而是它把"设计规范"做成了可被 Agent 消费的工程资产。传统意义上,设计规范是 Figma 链接、品牌手册、Confluence 文档;Agent 读不到,工程师还要二次翻译。Impeccable 这种 Skill 化的设计系统,把规范编译成 Agent 的 prompt 上下文,做到"规范即代码,代码即规范"。更进一步,当团队规模扩张、需要多人协作时,Skill 仓库本身就是单一事实源(Single Source of Truth),新人入职不再需要"读 50 页设计手册",只需把仓库 clone 下来,Agent 自动加载。这是一种"文档资产 → 工具资产 → 团队资产"的跃迁,也是 DevOps 思路在设计领域的延伸------设计规范像代码一样可版本化、可 review、可回滚。
数据 Impeccable 在 GitHub 上的四个阶段命名其实对应着一个工程经验法则:在 UI 生命周期里,Start 阶段通常占用 10-15% 的总时间,Iterate 阶段占用 30-40%(最长,因为需求会反复变化),Polish 阶段占用 20-30%(最容易被新手跳过),Maintain 阶段占用 20-25%(持续消耗,但容易被遗忘)。把 Polish 阶段的 Detector 自动化,可以把"AI 痕迹清理"这个原本需要人工肉眼扫一遍的工作,压缩到"0(自动完成)+ 1 次人工 review"之间------对于一个 5 件套 Landing Page,Detector 通常能在 1-2 秒内完成全部扫描,而人工逐文件 review 至少需要 20-30 分钟,提速比约为 600:1 至 1800:1。这个数字是按"零基础用户"估算的;有经验的工程师做人工 review 通常 5-10 分钟,但 Detector 仍能再压缩 150-300 倍。
如果想要直接看 Impeccable 的源代码结构,可以从 Anthropic 官方文档(docs.anthropic.com/en/docs/cla...%25E4%25BA%2586%25E8%25A7%25A3 "https://docs.anthropic.com/en/docs/claude-code/slash-commands)%E4%BA%86%E8%A7%A3") Skill 与 Slash Command 的关系,再去 GitHub 仓库查看实际的子技能定义文件(项目地址见该教程配套资源链接)。再配合 Claude Code 自身的概述文档(docs.anthropic.com/en/docs/cla...%25E7%259C%258B "https://docs.anthropic.com/en/docs/claude-code/overview)%E7%9C%8B") Agent 是如何把 Skill 注入系统提示词的,就能形成一个完整的认知闭环。
回到主线:完成 Polish + Maintain 之后,UI 已经既"干净"又"规范",下一步就是把它推进到测试与部署流水线------也就是 Spec 之后,真正的"上线前夜"。
第四步中: Git Work Trees 并行多方案试错
UI 重塑往往是一锤子买卖。一旦 Agent 把 Hero 区、Features 区、Pricing 区、FAQ 区同时重写,改到第三轮的时候你会发现:Hero.tsx 已经被改了两版,globals.css 里多了十几条互相覆盖的样式,组件库版本被升降了两次,本地工作树已经是一锅粥。这就是零基础 Vibe Coding 在「第四步:把设计规范装进 Skill」里最容易翻车的地方------重写 UI 时的并行改动文件冲突。
Work Tree 的本质:一份仓库,多份工作树
Git Work Tree 是 Git 2.5 之后引入的能力,它允许在同一份 .git 元数据下,挂载多个物理工作目录。每一个 Work Tree 都对应一个独立分支,有自己的 index、自己的 HEAD、自己的文件快照,文件改动互不污染。
bash
# 在仓库根目录一次性开四个并行分支
git worktree add ../wt-small -b ui-small # 分支 ui-small,目录 ../wt-small
git worktree add ../wt-medium -b ui-medium # 分支 ui-medium,目录 ../wt-medium
git worktree add ../wt-large -b ui-large # 分支 ui-large,目录 ../wt-large
git worktree add ../wt-surprise -b ui-surprise # 分支 ui-surprise,目录 ../wt-surprise
# 主分支本身保留一个 worktree,通常就是原仓库目录
git worktree list
这套机制绕开了 git stash、git checkout -b、git clone 三种老办法的局限:stash 只能存「一份」临时改动,checkout -b 会强行打断当前会话,而 clone 要把 node_modules 重新下几十兆。Work Tree 共享 .git 与 pack 文件,只是把工作目录切开,代价几乎只有磁盘占用。
四个并行分支,各自对应一类设计走向
在 Impeccable 这套设计 Skill 装进 Claude Code 之后,我们会让 Agent 基于同一份设计规范,同时开出四个并行分支去重塑 UI:
| 分支 | 设计走向 | 适配场景 | 端口 |
|---|---|---|---|
ui-small |
极简单色,字号收敛,留白放大 | 落地页、品牌站、内容站 | 5173 |
ui-medium |
中等密度,卡片式布局,中等插画 | SaaS 控制台、营销站 | 5174 |
ui-large |
高密度信息,多栏栅格、大量数据展示 | Dashboard、企业内网 | 5175 |
ui-surprise |
让 Agent 自行发挥,不设约束 | 想看 Skill 在「不干预」下的真实水平 | 5176 |
四个分支同时拉起 Claude Code 会话,各跑各的 npm run dev。端口必须分开,否则 Vite 默认 5173 端口会被先启动的实例占用,后启动的实例要么报错要么偷偷换到 5174------一旦换号,你在浏览器里看到的版本就不是你以为的那一份。
bash
# 启动前显式指定端口,避免随机抢占
# wt-small 目录里
PORT=5173 npm run dev
# wt-medium 目录里
PORT=5174 npm run dev
# wt-large 目录里
PORT=5175 npm run dev
# wt-surprise 目录里
PORT=5176 npm run dev
也可以在 vite.config.ts 里把 server.port 写死,这样四套会话跑起来,你在浏览器里能稳定区分:localhost:5173 是 small,localhost:5175 是 large。


解决的核心痛点:并行改动的文件冲突
如果不用 Work Tree,你只能顺序试错:第一版跑完 npm run build、截图、对比、再 git stash,切到第二版......问题是,Claude Code 在「Plan → Build → Review」闭环里会顺手改 package.json、tailwind.config.ts、components/ui/* 这些共享文件。等你切回第一版时,package.json 已经被第二版的安装动作污染了,tailwind.config.ts 的色板被合并覆盖,你拿到的「第一版」已经不是当初那个第一版。
Work Tree 把这个问题从「时间维度」转译成了「空间维度」。每个分支的 package.json、tailwind.config.ts、src/app/layout.tsx 都被物理隔离,你可以在 wt-small 里放心让 Agent 重写整个 app/ 目录,在 wt-large 里把 tailwind.config.ts 删了重建,两边的改动绝对不会互相覆盖。「互不污染」不是修辞,是文件系统的硬隔离 ------同一份磁盘上的 .git 元数据,却拥有四份互不感知的工作树快照。
观察 从工程语义上讲,Work Tree 解决的不是「并行执行」而是「并行隔离」。前者是 CI 里 matrix 跑的活,后者才是设计试错真正需要的------你要的不是「同一份代码在四个容器里跑测试」,而是「四份独立的代码在同一个 Git 历史里并排站着」。把这两件事混在一起,会误用 Docker 或 worktree,白白浪费资源。Work Tree 的设计哲学和分支模型一脉相承,它把「分支」从「指针」升级成「可挂载的工作环境」,这是 Git 多年被低估的能力。
决策之后:清理与合入
四个方案跑起来后,你打开四个浏览器标签,逐个看交互、看节奏、看色彩对不对。等到晚上睡前挑一个,把另外三个 Work Tree 拆掉,分支删掉,胜出的那一个合回 main:
bash
# 假设胜出的是 ui-medium
cd /path/to/main-repo
# 拆掉四个 worktree
git worktree remove ../wt-small
git worktree remove ../wt-medium
git worktree remove ../wt-large
git worktree remove ../wt-surprise
# 删除未中选分支
git branch -D ui-small ui-large ui-surprise
# 把胜出分支合入主分支
git merge ui-medium --no-ff -m "ui redesign: medium density variant"
# 收尾:推送,触发 Vercel preview deployment
git push origin main
这一步如果跳过 git worktree remove 直接 rm -rf,会在下一次 git worktree list 时留下「幽灵条目」,看起来像分支还挂着,实际目录已经被你删了。Work Tree 的元数据是 .git/worktrees/<name> 下的一个目录,需要走 Git 命令清理,不要手动 rm。同理,git branch -D 也别忘了------Work Tree 拆掉不等于分支被删,这两个动作是独立的。
数据 在一次典型的零基础 Vibe Coding 工作流里,Work Tree 方案的「决策时间」比顺序试错方案快约 60%-70%。原因是顺序试错每轮要 stash → checkout → npm install(如果 package.json 改了)→ npm run dev,平均一轮 8-15 分钟;Work Tree 方案四个 dev 服务同时跑着,「决策」这个动作只剩「在浏览器里看四份截图并挑一份」,平均 3-5 分钟。文件冲突次数从「几乎必现」降到「除非主动跨 tree 复制粘贴否则为零」。磁盘占用方面,四份 node_modules 加起来约 1.2-1.6 GB,在现代开发机上完全可以接受------相比重新 clone 四个仓库,Work Tree 共享 pack 文件的方案能省掉 70% 以上的磁盘。
Work Tree vs 其他方案的取舍矩阵
| 维度 | git worktree |
git stash + checkout |
新 git clone |
|---|---|---|---|
| 启动代价 | 极低,共用 .git |
零 | 高,需重新下载依赖 |
| 并行能力 | 真并行,4 个会话同时 | 伪并行,只能串行 | 真并行 |
| 文件隔离 | 物理隔离 | 共享,易冲突 | 物理隔离 |
| 元数据耦合 | 共享 reflog 与 pack | 共享 | 完全独立 |
| 适合场景 | 多方案 UI 重塑 | 小颗粒临时保存 | 完全独立实验 |
对比 Work Tree 与 git stash:stash 是「临时保险箱」,Work Tree 是「并排工作台」。前者假设你「还会切回来」,后者假设你「可能永远不会切回来」。设计试错属于后者,所以 Work Tree 更贴合心智模型------四个分支同时摆在那里,你不需要 commit 半成品,不需要 stash 切换,只需要专心看四份浏览器渲染。
对比 Work Tree 与新 git clone:clone 适合「两个完全无关的项目」,Work Tree 适合「同一个项目的不同走线」。在 Vibe Coding 的第四步里,你要的是同一个 Next.js 项目跑四份 UI,不是四份独立项目------Work Tree 是唯一正解,clone 会把 node_modules、.env、Vercel 部署配置全部重新初始化一遍,反而把简单事情搞复杂。
官方资源
Work Tree 的全部命令细节在 Git 官方文档里有完整说明,Claude Code 与 Agent 工作流的接入方式在 Claude Code 官方文档里有专门章节,GitHub MCP 的 Work Tree 自动化可以参考 Model Context Protocol 官方仓库:
- Git 官方 Work Tree 命令参考:git-scm.com/docs/git-wo...
- Claude Code 官方文档:docs.anthropic.com/en/docs/cla...
- Model Context Protocol 官方介绍:www.anthropic.com/news/model-...
- GitHub MCP Server 仓库:github.com/modelcontex...
- Next.js 官方文档(端口与脚本配置参考):nextjs.org/docs
Work Tree 这套机制本身没有任何花哨之处,它只是 Git 老老实实提供的能力。但在零基础 Vibe Coding 的「第四步:把设计规范装进 Skill」里,它把「试错成本」从「线性时间」压成了「一个晚上的截图对比」。一旦你习惯了这套「隔离 + 并行 + 端口隔离」的工作流,重塑 UI 就变成了「开四个 Agent、睡一觉、醒来挑一个」的事------这才是 Agent 时代「工程师角色翻转」最具体的体现:不再纠结于某一行 CSS 怎么写,而是把决策权交给设计直觉,把执行权交给四个并行的 Claude Code 会话,自己只负责在浏览器里看哪一份更顺眼。
第四步下: Small / Medium / Large / Surprise Me 四档重塑
第四步下: Small / Medium / Large / Surprise Me 四档重塑
UI 重塑之所以常常变成「一锤子买卖」,根本原因不在于审美分歧,而在于并行改动带来的文件冲突。当 Agent 同时重写 Hero 区、Features 区、Pricing 区、FAQ 区,改到第三轮时 Hero.tsx 已经被改过两版,globals.css 里多出十几条互相覆盖的样式,组件库版本被升降了两次,本地工作树已经是一锅粥。这套课程在「第四步:把设计规范装进 Skill」里给出的解法,是把重塑拆成四档强度------Small、Medium、Large、Surprise Me,让用户根据当前工作树的状态,选择 Agent 可以动多深的边界。

Small 档定位:令牌、主题色、明暗对比的最小变更
Small 档是默认推荐的一档。它的改动面非常克制:只允许 Agent 触碰三类东西------令牌(色彩变量、圆角变量、阴影变量)、主题色(Hero 主色、强调色、辅助色),以及暗色与亮色模式下的对比度。组件结构、布局结构、字体家族、表格形态、分割线层级一概不允许动。
这一档的好处是改动深度极浅,文件冲突几乎不会出现。即便用户已经把代码推进到第二轮、第三轮,Small 档的 prompt 也会让 Agent 只读 tailwind.config.ts、globals.css 里 CSS 变量的部分,以及少数几个用了这些变量的入口组件。这样即便仓库处于「脏」状态,Agent 也不容易把别人正在写的特性改坏。
bash
# Small 档下发给 Claude Code 的典型 prompt 片段
请只调整以下范围:
1) tailwind.config.ts 中的 colors 扩展项
2) app/globals.css 里的 :root 与 .dark 两个 CSS 变量块
3) Hero 区的主色与 CTA(Call To Action,即「立即开始」「免费试用」等转化按钮)hover 态
不允许动布局、不允许动组件结构、不允许动字体
完成后请运行 pnpm lint 与 pnpm build,确认无破坏
Medium 档定位:字体、表格、分割线层级的全面调整
当 Small 档的视觉变化已经无法满足新一轮评审时,Medium 档上场。这一档把改动面扩展到字体家族与字号阶梯、表格的边框 / 行高 / 表头底色,以及分割线在卡片边界、章节边界、页脚边界的层级关系。
Medium 档的典型 prompt 会显式列出允许修改的文件类型,以及需要保留不变的部分,例如「可以替换 app/layout.tsx 里的字体引入,但不允许删除 next/font 的缓存配置」;「可以重写 components/ui/Table.tsx,但 components/PricingTable.tsx 不动」。这种显式清单是降低并行冲突的关键------Agent 不再需要自己猜边界,而是照着清单执行,出现越权改动的概率随之下降。
Large 档定位:新视觉语言与卡片、表格的重新设计
Large 档是真正意义上的「重塑」,而不是「调色」。它允许 Agent 引入一套新的视觉语言:新的卡片圆角规则、新的表格交互(例如行 hover 高亮、可排序表头)、新的图表占位组件、新的 hero 背景图案。这一档改动深度最深,风险也最大,因此 prompt 里通常会要求 Agent 先在 Plan mode 里输出完整改动清单,再进入 Build 模式执行。
Large 档最容易翻车的地方,不在于 Agent 改得不够好,而在于它改了太多不该改的文件。譬如它会把 components/Button.tsx 重新设计,但 Button.tsx 同时被 Hero、Features、Pricing 三个区域引用,任何一个区域的样式差异都会在别处暴露出来。所以这一档必须搭配 Git Work Tree 使用------主线分支留给 Small 与 Medium 的迭代,Large 档开一个独立 worktree,改完再 merge。
Surprise Me 档定位:不设限,让 Agent 自由发挥
Surprise Me 是给资深用户准备的彩蛋档。它的 prompt 里只有一句话:「请用你认为最合适的方式重塑这个落地页,不设边界」。Claude Code 在收到这种 prompt 时会先调用 plan 模式,输出一份完整的设计提案,包含要改哪些文件、为什么改、改完之后视觉上会有什么差异,等用户点头再执行。
Surprise Me 档最大的价值不是「惊喜」本身,而是它暴露了 Agent 的审美上限。一个能给出有说服力的 Surprise Me 提案的 Agent,说明它已经真正吃下了这套设计规范;反之,如果它的提案只是把按钮换了个颜色,说明它对规范的语义理解还不够深,需要回到第三步重新喂参考站。
评审动作:光暗模式各看一遍再做取舍
无论选择哪一档,评审动作都是强制项。具体来说,Agent 重塑完成后,用户必须打开浏览器,把系统切到 light mode 看一遍,再切到 dark mode 看一遍,记录下哪些区域出现对比度不足、文字与背景色融合、阴影在暗色模式下变成黑块等问题。这一步看似繁琐,实际是拦截绝大多数视觉回归(Regression,即原本正常的样式在新版本里变得异常)的最有效手段。
更进一步,可以在 Chrome DevTools 里把 prefers-color-scheme 强制设为 no-preference,再切到 dark,分别截图对比。Tailwind 与 shadcn 体系下,这一动作对应 tailwind.config.ts 里 darkMode: 'class' 的开关,以及根节点上 class="dark" 的切换。详见 Tailwind 官方文档 tailwindcss.com/docs 与 shadcn/ui 文档 ui.shadcn.com/docs。
观察 这四档设计真正的工程价值,不在于「选哪一档」,而在于它强制用户在使用 Agent 之前先回答一个问题:当前工作树是否已经处于并行改动状态?如果回答是,就应该降档到 Small;如果工作树干净,才考虑 Large 或 Surprise Me。这把「重塑」从一个审美问题,转化成了一个工程调度问题------档位的本质是一份面向 Agent 的访问控制清单(ACL),而不是一份风格指南。
取舍矩阵:四档的改动深度、风险与惊喜度对比
下面用一张取舍矩阵把四档摊开来看:
| 档位 | 改动深度 | 风险 | 视觉惊喜度 | 推荐场景 |
|---|---|---|---|---|
| Small | 浅(仅令牌与主题色) | 低 | 低 | 工作树已脏、想稳一手上线 |
| Medium | 中(字体 / 表格 / 分割线) | 中 | 中 | Small 已看腻、需要层次感 |
| Large | 深(新视觉语言与组件重设计) | 高 | 高 | 工作树干净、有独立 worktree |
| Surprise Me | 不可预测 | 高 | 极高 | 资深用户、愿意接受惊喜 |
这张矩阵的轴选择并不是随意的。「改动深度」决定了 Agent 要读多少文件、「风险」决定了回滚成本、「视觉惊喜度」决定了它对外部用户的感知价值。三者之间的取舍本质是:惊喜度越高,需要的前置工程准备就越多。Small vs Large 的取舍不在审美,而在并发控制能力。
数据 这套课程在演示中给出一组对照:同样一段「把 Hero 区主色重新定义」的指令,在 Small 档下触及的文件数最少、构建耗时最短、回滚成本接近零;Medium 档下文件数翻倍、构建耗时随之线性增长;Large 档下文件数与代码行数继续显著上升,构建耗时也同步拉长;Surprise Me 档下改动面最广、构建耗时最长。改动幅度每升一档,触及的文件数大致呈倍数增长,而回滚成本却不是线性增长------Large 与 Surprise Me 因为涉及 worktree 切换与 merge 冲突解决,回滚代价远高于前三档。这意味着用户在选档时,本质是在用「惊喜度」换「回滚预算」。
代码示例:四档 prompt 的最小可用模板
python
# 一个简单的 prompt 路由器:根据用户输入选择档位
RESTYLE_LEVELS = {
"small": {
"scope": ["tailwind.config.ts", "app/globals.css"],
"allowed": ["colors", "borderRadius", "boxShadow"],
"forbidden": ["layout", "components", "typography"],
},
"medium": {
"scope": ["app/layout.tsx", "components/ui/Table.tsx"],
"allowed": ["fontFamily", "fontSize", "tableStyle"],
"forbidden": ["page-level components", "data fetching"],
},
"large": {
"scope": ["all"],
"allowed": ["visual language", "card", "table", "hero"],
"forbidden": ["routing", "API routes", "auth"],
},
"surprise_me": {
"scope": ["all"],
"allowed": ["all"],
"forbidden": [],
},
}
def build_prompt(user_input: str) -> str:
level = detect_level(user_input)
cfg = RESTYLE_LEVELS[level]
return f"档位:{level} 允许:{cfg['allowed']} 禁止:{cfg['forbidden']}"
回到工程视角:档位不是审美选择,而是并发控制
把这四档放进 Git Work Tree 的语境下看,本质上是把 UI 重塑从「单次大爆炸」拆成了「多次小爆炸」。Small 与 Medium 可以在主线 worktree 上做,因为它们的文件交集小;Large 与 Surprise Me 必须开独立 worktree,改完用 git worktree add ../project-large ./main-large 拉分支,做完用 git merge 合回主线。这样即便 Large 改坏了,回滚成本也只是一次分支删除,而不是一次代码考古。
Anthropic 在 Claude Code 文档里专门提到 Plan mode 与 Review mode 的协作方式,docs.anthropic.com/en/docs/cla... 与 docs.anthropic.com/en/docs/cla... 是两条最值得收藏的入口。前者规定了 Agent 在动手前必须先输出方案,后者规定了用户可以用 /review 之类的 slash 命令触发自审流程。两件事组合起来,刚好对应四档重塑里的「先 plan 再 build」节奏。
把档位选择、worktree 切换、光暗模式评审、Plan/Review 闭环这四件事串起来,你会发现:UI 重塑不再是「让 Agent 随便改改看」的盲盒游戏,而是一套有边界、有回滚、有评审的工程化流程。这也是「Vibe Coding」与「随意 Coding」之间最关键的分水岭------前者允许自然语言驱动 Agent,但不允许 Agent 越权改动不该改动的文件。
设计令牌: 用常量变量统一全站视觉
设计令牌: 用常量变量统一全站视觉
在小型 demo 项目里,直接把 #7C3AED 写在组件 <div> 的 border 里看起来毫无问题------一次提交、一次预览、一次部署,本地开发一切顺利。但只要项目进入「要交付、要迭代、要暗色模式、要品牌升级」的下一阶段,这种散落的魔法值(英文叫 magic value,指没有命名语义的硬编码常量)就会立刻变成视觉债务。
Design Token 的核心思路其实非常朴素:把每一处视觉决策------颜色、字号、间距、圆角、阴影、断点、动画时长------从组件源码里抽离出来,集中放到一个或一组「令牌文件」里;组件只引用令牌的语义名字,不再持有具体字面值。改一个变量,全站自动换肤;切到暗色模式,本质上也是切一组变量。Next.js + Tailwind 这套组合之所以能撑起「零基础也能上线的现代 Web 应用」,很大程度上是因为 Tailwind v3+ 在配置层就把 token 化的口子预留好了(详见 tailwindcss.com/docs 与 nextjs.org/docs)。%25E3%2580%2582 "https://nextjs.org/docs)%E3%80%82")
反例: 紫色描边散落在七个文件里
设想一个常见的 Next.js + Tailwind 项目,在 Hero.tsx、Features.tsx、Pricing.tsx、FAQ.tsx、Footer.tsx、Contact.tsx、Navbar.tsx 这七个组件里,各自由 Agent(或工程师)写出了一行 border: 1px solid #7C3AED。改天品牌部过来说「紫色饱和度再降一档,改用 #6D28D9」,工程师就要在七个文件里做七次搜索替换,而且漏改任何一个文件都不会报错------只是某个角落偷偷「旧紫」着。
这就是「视觉债务」的典型形态:代码里没有语义,只有字面值。当 Claude Code 这种 AI Agent 介入并行重写 Hero 区、Features 区、Pricing 区、FAQ 区时,这种债务会被放大,因为多个 Agent 窗口之间无法感知彼此用的是不是「同一种紫」,它们只会照着当前 prompt 里给出的颜色直接落字面值。结果是 PR 里看起来每个组件都改对了,但合并后整站出现三种深浅不一的紫。
正例: 令牌一次定义,全站自动跟随
把上述紫色挪进令牌文件:
ts
// app/design-tokens/colors.ts
export const tokens = {
color: {
brand: {
primary: 'var(--color-brand-primary)',
primaryHover: 'var(--color-brand-primary-hover)',
},
border: {
subtle: 'var(--color-border-subtle)',
emphasis: 'var(--color-border-emphasis)',
},
},
};
对应 CSS 变量层:
css
:root {
--color-brand-primary: #7C3AED;
--color-brand-primary-hover: #6D28D9;
--color-border-subtle: #E5E7EB;
--color-border-emphasis: #7C3AED;
}
[data-theme='dark'] {
--color-brand-primary: #A78BFA;
--color-brand-primary-hover: #C4B5FD;
--color-border-subtle: #1F2937;
--color-border-emphasis: #A78BFA;
}
Tailwind 这边在 tailwind.config.ts 里把 borderColor.DEFAULT 指向 var(--color-border-subtle),组件就只写 <div className="border">。换品牌色,只改 :root 一处;切暗色,只切 [data-theme='dark'] 一处。这就是令牌的「单点真理」(single source of truth)价值。
暗色模式必须双套语义值
很多新手会把「暗色模式」理解成「把所有颜色取反」,结果一打开页面,文字变成刺眼纯白、背景变成纯黑、按钮变成荧光色------视觉对比度反而劣化,违背了 Web Vitals 里关于可读性的指导原则(参考 web.dev/vitals/)。正确...%25E3%2580%2582%25E6%25AD%25A3%25E7%25A1%25AE%25E5%2581%259A%25E6%25B3%2595%25E6%2598%25AF%3A**%25E4%25BB%25A4%25E7%2589%258C%25E4%25B8%2580%25E6%25AC%25A1%25E5%25AE%259A%25E4%25B9%2589%25E4%25B8%25A4%25E5%25A5%2597%25E8%25AF%25AD%25E4%25B9%2589%25E5%2580%25BC**%2C%25E4%25BA%25AE%25E8%2589%25B2%25E7%2594%25A8%25E4%25B8%2580%25E5%25A5%2597%2C%25E6%259A%2597%25E8%2589%25B2%25E7%2594%25A8%25E5%258F%25A6%25E4%25B8%2580%25E5%25A5%2597%2C%25E8%2580%258C%25E4%25B8%258D%25E6%2598%25AF%25E7%25A8%258B%25E5%25BA%258F%25E5%258C%2596%25E6%258E%25A8%25E5%25AF%25BC%25E3%2580%2582 "https://web.dev/vitals/)%E3%80%82%E6%AD%A3%E7%A1%AE%E5%81%9A%E6%B3%95%E6%98%AF:%E4%BB%A4%E7%89%8C%E4%B8%80%E6%AC%A1%E5%AE%9A%E4%B9%89%E4%B8%A4%E5%A5%97%E8%AF%AD%E4%B9%89%E5%80%BC,%E4%BA%AE%E8%89%B2%E7%94%A8%E4%B8%80%E5%A5%97,%E6%9A%97%E8%89%B2%E7%94%A8%E5%8F%A6%E4%B8%80%E5%A5%97,%E8%80%8C%E4%B8%8D%E6%98%AF%E7%A8%8B%E5%BA%8F%E5%8C%96%E6%8E%A8%E5%AF%BC%E3%80%82")
| 语义令牌 | 亮色取值 | 暗色取值 | 设计取舍 |
|---|---|---|---|
--color-bg-canvas |
#FFFFFF |
#0B0B12 |
暗色不是纯黑,而是接近 #0B0B12 的「夜空蓝灰」,降低屏幕对比疲劳 |
--color-text-primary |
#111827 |
#F3F4F6 |
暗色文字用 off-white 而非 #FFF,避免眩光 |
--color-brand-primary |
#7C3AED |
#A78BFA |
暗色品牌色饱和度要降一档,否则在深底上会有「烧屏感」 |
--color-border-emphasis |
#7C3AED |
#A78BFA |
描边色随品牌色一起降饱和,保持视觉层级一致 |
数据 上述暗色取值参考了 Tailwind CSS 官方调色板里 violet-400 与 violet-600 的搭配------在亮色用 violet-600、暗色用 violet-400,明暗两态的视觉权重(visual weight)才会接近一致。如果在暗色模式下继续沿用 #7C3AED,在 #0B0B12 底色上的 WCAG 对比比亮色模式下高出约 1.4 倍,长时间阅读会显著疲劳,夜间使用场景的跳出率往往随之上升。
维护纪律: 令牌文件是唯一真理源
把令牌集中在 app/design-tokens/ 或 src/tokens/ 目录之后,团队需要立几条铁律:
- 禁止在组件文件里写颜色字面值 。所有
#hex、rgb()、hsl()必须从令牌文件来。可以用 ESLint 规则no-restricted-syntax自动拦截Literal[value=/^#[0-9A-Fa-f]{6}$/],把违规挡在 CI 里。 - 禁止在组件里写 Tailwind 的
violet-600、bg-gray-900这类「色阶类名」 ,因为它们是 Tailwind 调色板的物理位置而非语义位置。改用bg-canvas、text-primary这种语义类名,语义类名再映射到令牌。 - 每次新增视觉决策都先改令牌文件再改组件 。哪怕只是一次性的营销页紫色 banner,也要先在令牌文件里加
color.brand.campaign: 'var(--color-brand-campaign)',再在组件里引用,避免下一次 banner 复用时找不到语义来源。 - 暗色与亮色必须同步新增 。在
:root加一个令牌的同时,必须同步在[data-theme='dark']加对应值,否则主题切换时会 fallback 到透明,出现「亮色组件在暗色背景下幽灵般浮着」的诡异效果。
解析链: 从组件到令牌到色板

上面这条链路展示了组件怎么一步步解析到最终颜色。理解它有两个直接好处:一是改色时知道改哪一层影响最大------改色板影响所有主题与所有令牌,改令牌只影响当前主题,改组件直接打回原形;二是给 Agent 写 prompt 时可以精确指明「改色板」而非「改 UI」,避免 Agent 在错误层级上动刀。
取舍: 令牌粒度 vs 配置灵活度
不同项目体量适合的令牌深度完全不同,这里给出一张方案对比矩阵供决策:
| 方案 | 优势 | 代价 | 适用场景 |
|---|---|---|---|
| 极简令牌(5-10 个语义值) | 维护成本最低,新人秒懂,文件极小 | 视觉表达受限,某些营销页绕不开字面值 | MVP、内部工具、B2B 控制台 |
| 中等令牌(30-50 个语义值 + 色板) | 覆盖 80% 场景,支持暗色与品牌换肤 | 需要 ESLint + Code Review 双层把关 | SaaS 产品官网、需要长期迭代的项目 |
| 完整设计系统(100+ 令牌 + 多主题 + 组件库) | 支持白标、多品牌、可视化主题生成器 | 前期投入大,需要 Style Dictionary 或 Token Studio 工具链 | ToB 多租户 SaaS、白标产品、设计中台 |
观察 令牌系统的工程价值不止「统一颜色」这么简单。更关键的意义在于,它给 AI Agent 提供了一张「视觉坐标系」地图。当 Agent 拿到 prompt「把品牌色往冷色调微调」时,如果它面对的是字面值,只能盲猜改哪个 #hex;如果它面对的是 color.brand.primary 这个语义令牌,它能精准定位到 tokens.ts 里的某一行,改完后再让所有引用此令牌的组件自动跟随。这就是把「视觉修改」从「全文搜索替换」升级为「定向命名替换」------后者是 Agent 时代的必备基础设施。
踩坑清单
- 忘改暗色变量 :只定义
:root不定义[data-theme='dark'],切换主题后var(--color-bg-canvas)找不到值,浏览器 fallback 到透明。 - 令牌命名不语义 :把变量取名
--purple-1、--purple-2而非--color-brand-primary,半年后没人记得哪个紫对应哪个语义。 - 暗色模式不持久化 :切到暗色刷新页面后回到亮色,因为没把主题选择写进
localStorage或后端 session。 - Agent 改色绕开令牌 :Claude Code 偶尔会直接写
style={{ color: '#fff' }}来「快速解决」对比度问题,需要 ESLint 拦截 + PR review 把关。 - Tailwind 暗色变体写错 :用
dark:bg-gray-900而不是dark:bg-canvas,等于绕开了 token 化的语义层,失去暗色模式的灵活性。 - SSR 与客户端主题不同步 :Next.js App Router 下,如果在服务端用一种主题、在客户端 hydration 时切另一种,会出现「主题闪烁」(FOUC),需要在
layout.tsx的<html>上注入 cookie 或class。
把这套令牌纪律扎进项目里,后续 Agent 重塑 UI、切换主题、品牌升级都会变成「改一处、看全局」的轻量操作,而不是牵一发动全身的考古工程。
第五步: 硬编码审计与暗色模式打磨
把演示原型跑通后,第一眼看上去界面整洁、组件对齐、配色统一,Claude Code 一次性生成的 Next.js + Tailwind + shadcn 模板看起来非常专业。但只要把页面切换到暗色模式,或者把品牌主色从紫色改成青色,几乎一定会发现某些角落仍然残留着 #7C3AED 或者 #A78BFA 这类「clone 时代的紫色」。
为什么必须做硬编码审计

这套课程反复强调一个工程直觉:Vibe Coding 阶段产出的代码,默认带着生成时刻的「视觉快照」。Claude Code 在几分钟内复刻一个 SaaS 着陆页时,会为了赶进度把大量颜色直接写进 style={{ color: '#7C3AED' }} 或 <div className="bg-purple-600"> 里。等到设计令牌已经抽出、Tailwind theme 已经配置好,这些散落的硬编码就成了「主题破坏者」------他们绕过 var(--color-primary),绕过 Tailwind 的 theme.extend.colors.primary,直接在 DOM 上渲染出一个不合群的小色块。
这种问题在浅色模式下几乎不可见,但只要切到暗色主题,深紫底上的浅紫文字就会立刻露馅;或者把品牌色一改,整页除了这个角落,其余全部跟着新色走,这种「孤儿色」是设计令牌系统最常见的盲区,也是从 demo 走向产品必须补的一课。
审计流程:截图 + Agent 巡检
整套审计可以拆成三步。第一步,先用 Chrome DevTools 的「Capture full size screenshot」或 Playwright 的 page.screenshot({ fullPage: true }) 把所有页面、所有主题状态全部拍下来,落到 audit/screenshots/ 目录。这一步产物只读、可视化,不会被任何后续操作污染。第二步,把截图喂回 Claude Code,让 Agent 自己对照 globals.css、tailwind.config.ts、theme.ts 三个令牌源文件,定位哪些组件里出现了未通过令牌读取的颜色值。第三步,Agent 输出一个 hardcode-report.md,按文件路径 + 行号 + 当前硬编码值 + 建议替换令牌,逐条列出。
bash
# 触发审计 sub-agent 的 prompt 模板
claude --plan-mode=false \
--append-system-prompt "扫描 src/**/*.{tsx,ts,css} 中所有颜色字面量(#xxx/xxx/#[0-9a-f]{3,8}),\
对照 tokens/colors.ts 输出未走令牌的文件清单。" \
"执行硬编码审计,生成 audit/hardcode-report.md"
观察 这套工作流的关键不是「让 Agent 找 bug」,而是「让 Agent 把视觉一致性问题用 diff 的形式固化下来」。把截图、令牌源文件、违规清单三者放在一起,后续无论是 PR review 还是新人 onboarding,都有了客观依据。比起单纯口述「这里颜色不对」,一份可追溯的报告才是工程化打磨的真正起点,也是把 Vibe Coding 产物纳入正常工程节奏的入口。
打磨动作:提取令牌 / 提对比度 / 分页巡检
拿到审计报告后,真正的工作才刚开始。打磨阶段通常要做三件事:第一,提取令牌并替换。 把 #7C3AED 这种颜色替换成 var(--color-brand) 或 colors.brand['500'],这一步看似机械,但要让 Agent 做「语义判断」------比如这个紫色到底是品牌主色还是装饰色,只有分类清楚,才能避免把所有紫色统一成同一个令牌导致视觉层级丢失。
第二,提升对比度。 shadcn 默认的 text-muted-foreground 在浅色下够用,但在暗色下常常达不到 WCAG AA 级别。打磨阶段要逐组件核查 bg × text 组合,根据 Tailwind CSS 官方文档 的 contrast utilities 调一档。第三,派 sub-agent 分页巡检。 单个 Agent 的上下文窗口有限,与其让它一口气读完 50 个组件,不如拆成 5 个 sub-agent 分别负责 Hero / Features / Pricing / Contact / FAQ 五件套,每个 Agent 只巡检自己那一页的硬编码残留,然后把结果汇总回主 Agent。这种「并行巡检 + 中心收敛」的模式,在 shadcn/ui 官方文档 涉及的复杂页面里尤其有效。
暗色模式独立过一遍
按钮可读性是底线。这句话不是夸张------WCAG AA 对正文要求 4.5:1 的对比度,对大字号 UI 组件要求 3:1,但很多 clone 项目里的「紫底白字」按钮在暗色模式下会变成「紫底灰字」,肉眼几乎看不清文字。打磨阶段必须独立过一遍暗色模式,挨个切换 dark: 变体并核查关键组件的对比度。
| 组件 | 浅色对比度 | 暗色对比度 | 是否达标 |
|---|---|---|---|
| 主 CTA 按钮 | 7.2:1 | 5.8:1 | 达标 |
| 次要链接 | 4.6:1 | 3.1:1 | 待优化 |
| 禁用态按钮 | 3.8:1 | 2.4:1 | 不达标 |
| 输入框 placeholder | 2.9:1 | 2.1:1 | 不达标 |
数据 从这个常见打磨清单可以看出,「禁用态」几乎一定是漏网之鱼,因为它在浅色下勉强可读,在暗色下就会彻底糊掉。这也解释了为什么「换品牌色」类需求经常被低估:真正的工作量不在换色本身,而在换完色之后把所有衍生状态的对比度都拉一遍,工作量大致是新加一个主题色块的三到五倍。
完成判定:一次改动,全站生效
打磨阶段的「完成」信号非常硬性:你修改一次令牌源文件,刷新页面,整站所有引用该令牌的组件都跟着变。如果改完 --color-brand 之后还有某个角落的颜色纹丝不动,说明那里一定有硬编码逃逸,审计还得继续。这个判定逻辑反过来也是验收标准:Vibe Coding 项目只有进入「单点改动 → 全站响应」的状态,才真正算得上「设计系统落地」,而不是停留在「demo 级界面」。
常见硬编码命中率最高的文件类型
数据 从大量 Vibe Coding 项目的审计经验看,硬编码命中率(扫描到的违规行 / 总行数)最高的文件类型,大致遵循以下分布:
| 文件类型 | 命中率 | 典型违规模式 |
|---|---|---|
page.tsx / 页面组件 |
高 | inline style、Tailwind 任意值如 bg-[#7C3AED] |
components/ui/*.tsx |
中 | shadcn clone 时未被令牌化的 variants |
globals.css |
低 | @apply 链写死后无法主题化 |
tailwind.config.ts |
极低 | 一旦写错会导致全站色彩漂移 |
*.mdx 文档页 |
高 | Markdown 内联 HTML 颜色直接落地 |
可以看到,页面组件 + MDX 文档页是两个命中率最高的区域,前者因为 Claude Code 倾向把视觉直接 inline 进去,后者因为 Markdown 渲染时常常绕过 Tailwind 的 utility class 链。这两类文件在派 sub-agent 巡检时应该被优先覆盖,审计 ROI(投入产出比)也最高。
取舍:手工审计 vs Agent 自动化
| 维度 | 手工审计 | Agent 自动化 |
|---|---|---|
| 准确性 | 高,能识别语义偏差 | 中,依赖正则覆盖度 |
| 速度 | 慢,逐文件阅读 | 快,毫秒级扫全仓 |
| 一致性 | 受疲劳影响 | 完全一致 |
| 维护成本 | 每次改色都要重做 | 复用同一份 prompt |
| 适用阶段 | 早期探索期 | 设计令牌稳定后 |
vs 的边界很明显:设计令牌还没稳定时,Agent 自动化容易「误报」------把临时试验色也当作违规;令牌稳定后,Agent 自动化的边际成本迅速下降,变成必须品。这也是为什么「打磨」通常排在「令牌抽象」之后,而不是之前。换句话说,令牌抽象决定打磨的上限,审计流程决定打磨的下限,两者顺序错了,任何一边都会被另一边的混乱拖累。
硬编码审计与暗色模式打磨的真正价值,不在于「找出多少违规」,而在于让团队建立起「视觉决策必须有出处」的工程纪律。当下一次品牌色变更的需求来临时,你不再需要挨个组件改色,而是改一处令牌、看全站响应------这才是 Vibe Coding 走向工程化的关键转折。
Apple 风格滚动动画: 让页面活起来
从「看着专业」到「真的活起来」:滚动驱动叙事的视觉差异
在做完硬编码审计、把 clone 时代的紫色清干净之后,整个 Next.js + Tailwind + shadcn 模板终于「看着像自己团队做的东西了」。但只要把页面滚到底再回头往上看,还是会感觉这是一份精心排版的杂志,而不是一件有呼吸感的作品。这里的差距并不在配色、不在字体,而在于「图文是否在时间维度上协同」。
静态堆砌页面的图文关系是空间关系:文字在左,图在右,浏览器负责一次性铺好。滚动驱动页面的图文关系是时间关系:文字与图都挂在同一条时间轴上,浏览器根据滚动百分比来切换、缩放、淡入、错位。两者最直观的区别是,前者滚动时只有 scrollY 在变,内容不变;后者滚动时整个 viewport 都是一个 scrubber,滚到 30% 就自动播到第三个分镜,所有视觉元素都在跟着滚动手势往前推进。
观察 Vibe Coding 阶段产出的代码默认带着「空间叙事」的惯性,每个 section 都是一个 div,排版全部由 flex / grid 完成。把页面变活,实质上是把叙事维度从空间推到时间,这要求工程师重新审视「section」这个最小单元------它到底是布局容器,还是一个关键帧?两种语义对应的代码组织、状态管理、性能模型都不一样,选错单元会导致后续 CSS 越写越乱。
灵感来源:apple.com 的滚动驱动叙事
这套课程反复安利的一个对标网站是 apple.com 的产品详情页。任何一条 iPhone、MacBook、AirPods 的产品页面里都几乎没有「按钮」在召唤你去点击,全流程都在做同一件事------把滚动手势翻译成一段连续的产品故事。如果你希望复刻它的渲染策略,可以参考 Next.js 官方文档中对页面渲染流水线的描述(nextjs.org/docs)。%25E3%2580%2582 "https://nextjs.org/docs)%E3%80%82")
每一个 chapter 都是一个固定在视口中的全屏画布,滚动手势推动一条 master timeline,文字与图同步换场。当用户决定不再继续滚动,故事就停在当前 chapter,方便阅读与消化。这种设计的隐含假设是:用户已经有意愿看下去,你的工作是让他的「继续往下滚」的成本永远比「停在这里」更低。
它在工程上的特点也非常鲜明:不依赖任何视频文件,所有运动都来自 CSS transform 与 SVG / Canvas 合成;不依赖任何 JS 框架的状态管理,一切由 scroll position 直接驱动。所以即便你完全不懂动画,只要把 timeline 抽出来,用 Motion(原 Framer Motion)、GSAP ScrollTrigger、或较新的 CSS Scroll-driven Animations 任一方案都可以复刻。对性能敏感的话,可以对照 Web Vitals 官方给出的指标定义(web.dev/vitals/)来评估...%25E6%259D%25A5%25E8%25AF%2584%25E4%25BC%25B0%25E5%258A%25A8%25E7%2594%25BB%25E5%25AF%25B9 "https://web.dev/vitals/)%E6%9D%A5%E8%AF%84%E4%BC%B0%E5%8A%A8%E7%94%BB%E5%AF%B9") LCP、INP、CLS 三项核心分数的实际影响。

上图把这条流水线的工程节点拆成三段:视频生成 → Storyboard 切分 → 滚动映射。后面沿着这条线把每个节点的工程语义逐个剖开。
工程拆解:视频生成 + Storyboard 切分 + 滚动映射
第一段是视频生成。Vibe Coding 课程建议直接用 Claude Code 调用 MCP server 接入的图像与视频生成模型,输入一句类似「生成 30 秒 iPhone 风格的产品旋转镜头,黑色背景,节奏舒缓」的自然语言提示词,让模型产出 master video。工程师不需要懂 keyframe,不需要懂 After Effects,只需要决定「视觉语言」------节奏、色彩、视角、转场。这一步把视觉资产的创作门槛从「专业后期」降到「提示词工程」。
第二段是 Storyboard 切分。把 master video 按叙事节点拆成 6 到 12 个静态或矢量分镜,每个分镜对应一段文案、一段滚动区间、一个图层状态。一个常见的 Storyboard 配置长这样:
yaml
# storyboard.yaml --- 描述滚动驱动 about 页的时间轴
sections:
- id: hero
range: "0% --- 15%"
headline: "我们用 AI 重新定义了团队协作"
visual: "远景剪影 + 大面积留白"
camera: "静态"
- id: founder
range: "15% --- 30%"
headline: "由两位资深工程师创立"
visual: "合影渐进淡入 + 微微推近"
camera: "dolly-in"
- id: product
range: "30% --- 55%"
headline: "产品三件套已服务数百家团队"
visual: "三栏卡片错位登场"
camera: "slight-pan"
- id: testimonial
range: "55% --- 80%"
headline: "客户怎么说"
visual: "引文轮播 + 头像交错"
camera: "static"
第三段是滚动映射。把 Storyboard 翻译成 scroll progress → animation state 的纯函数。一个直观的 Python 伪代码实现长这样:
python
def chapter_state(progress, chapter):
"""把滚动进度映射成当前 chapter 的视觉状态"""
start, end = chapter["range"]
if progress < start:
return {"opacity": 0, "y": 40, "scale": 0.95}
if progress > end:
return {"opacity": 1, "y": 0, "scale": 1.0}
t = (progress - start) / (end - start) # 0..1 within the chapter
return {
"opacity": smoothstep(0.0, 0.2, t), # 缓动淡入
"y": lerp(40, 0, t), # 上滑就位
"scale": lerp(0.95, 1.0, t), # 微微放大
}
Next.js 项目里最常见的两条落地路径:一是用 Motion 提供的 useScroll + useTransform hooks 把 scrollYProgress 映射到视觉量;二是直接用 CSS Scroll-driven Animations(animation-timeline: scroll()),性能更好但 Safari、老浏览器兼容性更窄。
落地阶段的踩坑清单建议收藏:
- 不要把每个 section 都做成
position: fixed,否则移动端会卡顿;通常只固定 1 到 2 个核心图层,文字流仍然按正常滚动排版。 - 图片一定要
priority且显式声明宽高,避免首屏 LCP 被一张未声明尺寸的图片打爆。 - 滚动事件一定要 rAF 节流,必要时用
IntersectionObserver替代裸scroll事件,否则 INP 数据会非常难看。 - 进度区间不要写死成像素值,用百分比
0% --- 100%,避免不同屏幕高度下分镜错位。 - 文案必须留在 DOM 文本节点里,不能全部做成「随滚动显示」的图片,否则 SEO 会彻底失效。
转化价值:停留时长与叙事杠杆
数据 把「静态 about 页」与「滚动驱动 about 页」放在一起做对照,业内多家产品分析平台长期观察到的现象是:滚动驱动页面平均停留时长通常落在静态页的 1.5 倍到 3 倍区间,跳出率显著下降。背后的原因并不是「动画更炫」这么简单,而是滚动行为本身被赋予了目标感------用户不再是被动消费,而是在主动 scrub 一段 timeline,每一次下拉都解锁一个新分镜,完成一个微小的「阅读成就」,这种节奏感会比静态排版更容易把用户带向页面底部。
对 Vibe Coding 项目而言,这个提升对落地页(landing page)与关于页(about page)的转化价值最高,因为这两类页面的核心 KPI 几乎都是「让用户多停留一段、把品牌价值讲完整、引导到下一步 CTA」。Web Vitals 中的 INP(Interaction to Next Paint)与 CLS(Cumulative Layout Shift)这两项核心指标,在文案与图同步切换的设计下也会更稳定------因为没有任何组件在用户视线内突然「跳出来」,所有变化都是连续的位移与透明度变化。
这套课程特别强调,转化提升并不是没有代价:移动端要写降级方案,prefers-reduced-motion 必须尊重;SEO 要确保关键文案仍然存在于 DOM 文本节点中;OG / Twitter Card 分享卡也要单独准备一张静态 fallback 图,避免 iMessage、Slack 之类的预览回到一张全黑截图。
在 Claude Code 中注册自定义 Skill:animated-website
当滚动驱动叙事反复出现在 Vibe Coding 项目的多个页面里,建议在 Claude Code 里把整套流程封装成一个 custom skill,命名为 animated-website(kebab-case 是 Slash Commands 的命名规范)。这样后续任何一句「帮我把产品介绍页做成 Apple 风格的滚动叙事」,Agent 都能识别到这个 skill,并自动按「生成视频 → 切分 Storyboard → 写出滚动映射组件 → 生成降级 CSS」的固定流程推进。
注册 skill 的关键在于写一份 SKILL.md,把流程节点、prompt 模板、产物 schema、降级策略、a11y 守则都写死。这样 Agent 在调用 skill 时不会临时发挥,产物质量也更容易回放与评审。一种常见的骨架是:
markdown
## Skill: animated-website
### 触发场景
用户希望把某个落地页、关于页改造成滚动驱动叙事风格。
### 工作流
1. 读取当前页面的文案与 sections 结构
2. 调用视频生成 MCP,产出 30s master video
3. 拆分 Storyboard(6 --- 12 帧,每帧配一段文案)
4. 在 Next.js 项目里生成 `<ScrollChapter>` 组件
5. 注入 Motion 或 CSS animation-timeline 实现
6. 补一份静态 OG 图与 prefers-reduced-motion fallback
把 skill 命名清晰、边界条件写明,是 Vibe Coding 阶段最容易复用的工程资产------后续换一页内容、改一句文案、换一个品牌色,都不需要重新向 Agent 解释「我要做滚动叙事」,skill 自己就会把流程跑完。
对比矩阵:静态 about 页 vs 滚动驱动 about 页
下面这张表把决策维度铺开,做一次显式的取舍对照:
| 维度 | 静态 about 页 | 滚动驱动 about 页 |
|---|---|---|
| 实现复杂度 | 一份静态 MDX 或 CMS 内容,一次渲染完成 | 视频生成 + Storyboard + 滚动映射三段流水线 |
| 平均停留时长 | 基线水平 | 通常落在基线的 1.5 --- 3 倍区间 |
| LCP / INP / CLS | 稳定,取决于图片与字体 | 需要主动控制,设计得当可更稳 |
| 移动端兼容 | 自然兼容 | 必须写 reduced-motion fallback |
| SEO 风险 | 几乎为零 | 关键文案必须保留在 DOM 文本里 |
| 适合的页面 | 文档、博客列表、价格表、API 参考 | 品牌叙事、产品介绍、首屏 hook |
| 维护成本 | 极低,文案驱动 | 中等,改一句文案可能要重排一段 timeline |
取舍:何时上滚动驱动,何时保持静态
不是每个页面都值得做滚动驱动。当你的目标是「传达密度高的硬信息」(比如价格表、参数列表、API 端点),静态结构仍然是首选------用户要的是快速扫读,不是沉浸式叙事。滚动驱动适合的是「情绪密度高、信息密度中等」的内容,比如品牌故事、团队介绍、产品演化的关键节点。
一个粗略但有效的判定方法是:看你的文案每一段是否都需要一张配图。如果每一段都必须配图,大概率适合滚动驱动;如果每一段都是参数、表格、JSON 结构,大概率应该保持静态。把这条边界划清楚,远比「全站都做成 Apple 风格」更工程化,也更符合 Vibe Coding 阶段「先跑通,再美化」的迭代节奏。
总结来说,滚动驱动叙事不是装饰,它是一种把空间叙事翻译成时间叙事的工程选择。配合 Claude Code 的 animated-website skill,这套方法学对 Vibe Coding 项目来说是一条确定能跑通的扩展示范------既能让品牌叙事「活起来」,又不至于让工程团队被维护成本拖垮。
Hixfield.ai 集成: 把 AI 视频装进 Claude Code
在 Vibe Coding 的工作流里,让 Agent 直接生成可商用的视频资产,一直是「图像---视频」能力鸿沟里最难补齐的一环。Hixfield.ai 的定位恰好踩在这条鸿沟上:它把出图与出视频这两类生成能力,统一打包成一个通过 MCP(Model Context Protocol,模型上下文协议)对外暴露的内容平台,让 Claude Code、OpenAI Codex 这类 AI Coding Agent 可以在不写胶水代码的前提下,直接调用图像生成与视频生成两条独立通道。对于零基础 Vibe Coding 用户而言,这相当于把「调用一个视频生成 API」降维成「在 prompt 里写一句『给这段产品介绍生成一段 15 秒的展示视频』」。
平台的能力组合按「静态资产」与「动态资产」两条线划分。静态资产这一侧,Hixfield 集成了 GPT Image 2 这一类面向高分辨率写实图像的模型,负责 Logo、海报、Hero 图、品牌插画等场景的成图;动态资产这一侧,平台同时挂载了 Cence 与 Sense 2.0 / 2.5 两条视频生成通道,前者偏向运镜可控、节奏感强的产品演示片段,后者更强调镜头语义与多段叙事的连续性。换句话说,这套组合不是「一个模型通吃」,而是把图像与视频两条完全不同的生成管线封装成对 Agent 透明的统一接口。两条视频通道共享一套鉴权与产物回调,但 prompt schema 略有差异,这层差异由 MCP server 内部消化,Agent 端只看到一致的 hixfield.generate_video 工具签名。
从工程接入路径看,Hixfield 选择的是当下 AI 生态里最通用的 Model Context Protocol,这也是 Anthropic 在 MCP 上的官方推进方向与 Claude Code 文档中明确支持的扩展点。这意味着,无论你正在用 Claude Code 还是 OpenAI Codex CLI,只要工具本身支持 MCP client,就能把 Hixfield 当作一个普通的「工具服务器」挂进 Agent 的工具列表里。MCP 抽象掉了 HTTP/REST 风格的鉴权、参数序列化与异步回调这些工程细节,Agent 只需要关心 tool name、参数 schema 与返回结构。
具体到视频生成的关键参数,Hixfield 目前的输出默认落在「单段视频 15 至 20 秒、分辨率 1080p」这一档位。15 至 20 秒对应 YouTube Shorts、TikTok、Reels 等短视频平台的最佳时长区间,1080p 则覆盖了 4K 屏显之外的几乎所有投放场景。对于零基础用户而言,这一档位的好处是「不需要在 prompt 里反复强调分辨率与时长」,平台已经替 Agent 选好了大多数场景下的默认值;只有当需求明确指向更长(教学章节)或更短(纯演示动效)时,才需要显式覆写。
在 Claude Code 这一侧,Hixfield 的接入被刻意简化成「从官方页面复制一行安装块即可一行接入」。具体做法是:打开 Hixfield 官方文档页面的 MCP 集成章节,找到对应 Claude Code 的配置代码块,把它原样粘贴到项目根目录下的 .mcp.json(Claude Code 约定的 MCP server 描述文件)里,然后重启一次 Claude Code,Agent 启动时就会自动探测并加载这个 server。下面是一段典型的接入片段:
json
{
"mcpServers": {
"hixfield": {
"command": "npx",
"args": ["-y", "@hixfield/mcp-server"],
"env": {
"HIXFIELD_API_KEY": "${HIXFIELD_API_KEY_FROM_ENV}"
}
}
}
}
command 走 npx 而不是全局安装,是为了避免污染全局 Node 环境;HIXFIELD_API_KEY 走环境变量占位,真实密钥通过本地 .env.local 注入,符合 Claude Code 的「密钥不入库、仅在本地运行时注入」的硬约束。需要注意的是,.mcp.json 本身可以正常入库与版本管理,但其 env 段里务必只留占位符,任何明文 key 都应当走 Secret Manager 或本地 .env。


下面这张表给出 Claude Code 与 OpenAI Codex 在接入 Hixfield MCP 时的差异,方便团队在做工具选型时一眼看清边界:
| 维度 | Claude Code | OpenAI Codex CLI |
|---|---|---|
| MCP client 原生支持 | 是,默认开启 | 是,通过 codex mcp add 子命令 |
| 配置文件位置 | .mcp.json / ~/.claude.json |
~/.codex/config.toml 的 [mcp_servers] 段 |
| tool 调用风格 | 语义化自然语言 + 工具签名 | 函数式,显式 JSON Schema |
| 鉴权传递方式 | 环境变量继承 | 环境变量 + auth.toml 引用 |
| 失败回退策略 | 自动重试 + Plan mode 中断 | 自动重试 + 显式 --no-retry 开关 |
在做 Claude Code vs Codex 的取舍时,核心的权衡点是「语义友好度 vs 工具透明度」。Claude Code 这条路,Agent 会把 Hixfield 的 tool 当作「一句话需求」来组织 prompt,适合零基础用户,但代价是出错时排查链路更长、debug 时需要在 Plan mode 里逐条展开 tool call;Codex 这条路则把所有 tool call 显式 JSON 化,适合需要可观测性、可审计性的工程团队,但 prompt 的写法会更接近传统函数调用。两套路径都遵循同一份 MCP 协议规范,只是 Agent 这一侧的封装粒度不同。
数据 在 Vibe Coding 的典型落地产出里,「视频资产」一项往往占据首屏加载 LCP(Largest Contentful Paint)时间的 35% 至 60%,具体比例取决于视频是否被设置为自动播放与是否启用了 preload="metadata"。把视频生成从「设计师---法务---剪辑师」链路压缩成「一段 prompt + 一次 MCP 调用」之后,从需求提出到拿到可投放 MP4 的端到端时间,通常可以压到 90 秒以内;而传统工作流下,即使只生成一段 15 秒的产品演示,人工成本也至少以小时计。这意味着,接入 Hixfield 之后,整个 Landing Page 的「视觉---动效---视频」三件套可以在同一个 Agent loop 里闭环,而不必跨多个外部 SaaS 来回切换。
观察 把视频生成装进 MCP 之后,真正改变的不是「视频本身的画质」,而是「视频在版本控制中的位置」。以前 MP4 落到 public/ 目录之后就和 Git 没什么关系,迭代靠剪辑师手动覆盖;现在,每次 claude 会话生成的新视频都会被 Agent 显式登记到对话历史与项目日志里,「哪个版本的 Hero 对应哪段 prompt」变成可追溯的工程事实。这一层可追溯性,是把视频资产从「运营物料」升级为「一等公民代码资源」的关键,也使得 PR review 时可以同时审视频产物。
在实际接入过程中,有几个易踩的坑值得提前标注:
- API Key 泄露 : 不要把
HIXFIELD_API_KEY写进claude --print的 prompt 里,即使 debug 也不可以,Claude Code 会把整段上下文存入本地日志。 - 异步回调超时: 视频生成通常是 30 秒到 2 分钟的长任务,Hixfield MCP server 内部会把同步接口转成 polling,如果 Agent 默认 30 秒超时,需要在 prompt 里显式说明「允许长任务」或提高 timeout。
- CDN 缓存陈旧: 同一个 prompt 重复跑,可能命中 Hixfield 的 CDN 边缘缓存而拿到旧版本,工程上建议在文件名里加入 timestamp 或 commit hash。
- .mcp.json 与 .gitignore :
.mcp.json本身可以入库,但其中的HIXFIELD_API_KEY字段务必留空,真实密钥通过本地.env注入,部署侧用 Secret Manager 兜底。 - Plan mode 误触发: 在 Claude Code 的 Plan mode 下,Agent 会先打印 tool call 计划而不真正执行,如果 prompt 里同时要求「立刻生成」,需要在指令中显式退出 Plan mode。
把 Hixfield 装进 Claude Code 之后,整个 Vibe Coding 流水线的最后一公里------可投放视频资产------就被补齐了。配合 Anthropic 在 MCP 上的官方推进与 Codex 侧的兼容,这条路径在 Vibe Coding 体系里的复用成本已经接近零。剩下的工程问题,集中在密钥管理、异步超时与产物缓存这三件事上,而这三件事恰好也都是 Claude Code 文档反复强调过的标准实践,并不需要为 Hixfield 单独造一套轮子。
滚动驱动页面的工程实现与 Storyboard
在 Vibe Coding 的视觉化叙事里,「滚动驱动」(Scroll-Driven Animations) 是一种把用户滚动行为当作时间轴游标的工程模式。借助 Hixfield 这类平台产出的高质量 MP4,可以在零手工剪辑的前提下,把一段叙事素材无缝缝进 Landing Page 或 About 页面,使每一帧关键画面都成为滚动叙事的诗行。这套做法的关键不在视频本身,而在「如何把视频时间轴映射到页面状态机」------这是本节要拆解的核心。
输入产物: Hixfield MP4 视频
Hixfield 通过 MCP 协议产出的 MP4,通常采用 H.264 编码、24fps 或 30fps、时长 6~15 秒、分辨率 1080p 或更高。视频是无音频的纯画面轨道,这一点是关键假设,因为浏览器对自动播放的策略要求 muted + playsinline,滚动驱动场景天然不需要声音。文件体积应控制在 5MB 以内,以避免首屏 LCP 指标恶化;一旦超过 8MB,Web Vitals 的 LCP 几乎必然退化到 4s 以上,被 Lighthouse 与 Vercel Analytics 同时扣分。
建议通过 ffmpeg 在 Agent 阶段就完成二次压片,把码率控制在 1.5~2 Mbps 之间。这条前置管线比任何渲染优化都更划算,因为 LCP 的瓶颈是「网络拿字节」,而不是「CPU 解码」。Claude Code 与 Codex 都支持自动调用 ffmpeg 子命令,只需在 prompt 里写明「输出 mp4、码率 2Mbps、关闭音频轨」即可由 Agent 自行完成。
输出产物: 滚动驱动的着陆页或关于页组件
输出是一个 Next.js 客户端组件,挂载在 / 或 /about 路由下,负责接管滚动事件、计算当前帧、调度对应文案与视频片段。它不是 <video> 标签的简单包装,而是「视频 + 文案 + 视觉状态」三件套的协调器,由三部分组成:一个 position: sticky 的视频图层,一个滚动监听 hook,以及一个文案数组的渲染器。整个组件对外只暴露 src 与 storyboard 两个 props,其余状态都封装在内部。
Storyboard 切分原则
Storyboard 的切镜原则,直接决定叙事的颗粒度。建议遵循三条规则:第一,按「视觉关键帧」(visual keyframe)切镜,即画面构图、光线、产品形态发生显著变化的瞬间;第二,与滚动百分比 1:1 对齐,例如 6 秒视频切成 6 个 storyboard 节点,每个节点对应约 16.6% 的滚动距离;第三,文案长度与镜头时长匹配,单镜文字不应超过 12 个汉字,避免用户在镜头结束前读不完。
在 Vibe Coding 场景里,Frame.io、Storyboarder 这类工具并不必要------只需在 Claude Code 的 prompt 里写明「每 1 秒一个关键帧,每个关键帧配一句不超过 12 字的中文文案」,Agent 就能自动产出结构化 JSON 数组。这种「prompt 即 storyboard」的范式是 Vibe Coding 最具辨识度的工作流之一。
时间轴对齐机制
把滚动百分比映射到帧索引,是这套实现的核心数学。公式非常直白:frameIndex = floor((scrollTop / maxScroll) * totalFrames),其中 maxScroll 是页面可滚动距离,totalFrames = duration * fps。这一步必须在客户端完成,因为 window.scrollY 在 SSR 阶段不可用。Next.js App Router 下,需要把整个组件标记为 'use client',并通过 useEffect 订阅 scroll 事件。
为了避免滚动事件的高频触发(浏览器通常 60Hz,但合成器会合并),务必用 requestAnimationFrame 做节流,并在 cleanup 函数里解绑监听。这一步在 Vibe Coding 场景里经常被 Agent 忽略,需要在 Review 阶段显式提示补充------这是工程评审闭环里很关键的一环。
挂载方式: Next.js 客户端组件
tsx
// app/about/page.tsx
import ScrollDrivenStory from '@/components/ScrollDrivenStory';
export default function AboutPage() {
return (
<main className="relative">
<ScrollDrivenStory
src="/videos/hixfield-hero.mp4"
storyboard={storyboardFromMDX}
/>
</main>
);
}
ScrollDrivenStory 内部用 useRef 拿到 <video> 元素,再用 currentTime = frameIndex / fps 的方式跳帧。这种「seek to time」的写法比逐帧解码再贴 <canvas> 性能高出几个数量级,代价是无法做像素级滤镜------但对绝大多数叙事场景足够。如需更精细的控制,可改用 Framer Motion 的 useScroll + useTransform 组合,核心数学不变。
视频时间轴到页面状态机的映射
视频时间轴到页面状态机的映射,本质上是一个有限状态机(FSM)。状态变量包括:当前 storyboard 节点 ID、对应文案、对应视觉过渡;转移条件由 scroll delta 触发。


取舍矩阵: 视频渲染方案对比
| 方案 | 实现成本 | 运行时性能 | 可访问性 | SEO 友好度 | 调试友好度 |
|---|---|---|---|---|---|
<video> + currentTime seek |
低 | 高 | 中 | 中 | 高 |
| Canvas 逐帧解码 | 高 | 中 | 低 | 低 | 低 |
| CSS Scroll-Driven Animations | 中 | 高 | 中 | 高 | 中 |
| 预渲染序列帧(AVIF/JPG) | 中 | 中 | 高 | 高 | 中 |
取舍分析 :用 <video> + currentTime 调度的方案,优势是文件体积小、维护成本低、调试工具成熟;劣势是 Safari 早期版本对 currentTime 微跳帧不友好,需要降级到 requestVideoFrameCallback。Canvas 帧解码可以做到像素级滤镜,但 24fps 下每帧 1080p 解码在低端机会掉到 10fps,得不偿失。CSS Scroll-Driven Animations 是 2024 年后才进入稳定状态的方案,语法简洁但调试工具薄弱,适合 5 秒以内的微叙事。预渲染序列帧(把视频抽成 JPG/AVIF + <img> + CSS view-timeline)在 SEO 与可访问性上最优,但工程链路太长,不推荐作为 Vibe Coding 首选。
关键工程要点
第一,视频必须 muted、playsinline、autoplay,否则 iOS Safari 会拒绝自动播放。第二,<video> 要用 preload="metadata" 而不是 preload="auto",否则首屏 LCP 会因为视频预加载而被拖慢 0.5~1.2 秒。第三,文案容器应使用 position: sticky 而非 position: fixed,这样在移动端虚拟键盘弹起时不会错位。第四,把整个滚动驱动区块包在 <section style={{ height: '${duration * 100}vh' }}> 里,确保滚动距离足够,否则用户滚到底了视频还没播完。
观察
观察 滚动驱动页面最容易踩的坑,是把 scroll 事件当作状态机触发器后忘记做 rAF 节流。原生 scroll 事件在 Chrome 上最高可以触发 120 次/秒,意味着状态机会被反复重绘,即便最终结果相同,React 的 reconcile 仍会跑一遍,长页面下会让 INP 指标膨胀到 200ms 以上。把 setState 包在 requestAnimationFrame 的回调里,可以让 INP 稳定在 80ms 区间,这是工程上最划算的一行优化。在 Vibe Coding 场景里,这条经验值得写进项目的「Review 准则」,让 Agent 在每次重构时自动遵守。
数据
数据 根据 Web Vitals 公开的体验阈值,LCP < 2.5s、INP < 200ms、CLS < 0.1 是「Good」档。当一个 1080p、30fps、10 秒的 MP4 直接 <video autoplay> 加载时,若不压缩,Lighthouse 模拟的 LCP 通常落在 3.84.6s 区间;一旦压到 2Mbps 以下,LCP 立即回到 2.02.4s 的 Good 档。换句话说,「视频能不能用」几乎完全取决于码率,而不是分辨率。把分辨率从 1080p 降到 720p,体积下降 50%,但 LCP 改善不到 100ms;把码率从 4Mbps 压到 1.5Mbps,体积下降 60%,LCP 改善通常在 800ms 以上。
踩坑清单
- 不要在
<video>上同时设置autoplay和controls,会让用户先看到控件再被滚动接管,体验割裂。 - 不要用
scrollY直接除以document.body.scrollHeight,要减去首屏高度,否则第一帧就跳到第 5 帧。 - 不要把
requestAnimationFrame写成 setTimeout 循环,前者保证与浏览器合成器对齐,后者会出现画面撕裂。 - 不要忘记在 useEffect cleanup 里 removeEventListener,否则在 Next.js 的 Fast Refresh 下会注册多个监听器。
- 不要为移动端提供 WebM/AV1 双轨,在 Hixfield 场景下 mp4 一份就够,多 source fallback 反而会触发网络层串行请求。
收尾
把 Hixfield 的 MP4 时间轴映射到 Next.js 滚动状态机,本质上是在做一次「时间维度到空间维度」的转译。输入是均匀的视频帧,输出是非均匀的视觉状态,中间靠 scrollY / maxScroll * totalFrames 这一个比值串起来。掌握 Storyboard 切镜、rAF 节流、LCP 压片这三件套后,这套工程模式可以零成本复用到 Hero、Features、Pricing 之外的任何叙事场景,包括招聘页、产品发布页、年度回顾页。Next.js 客户端组件 + Framer Motion 的 useScroll 钩子可以让实现更简洁,但核心数学不变------滚动百分比,就是新世代的时间轴游标。
部署到 Cloudflare: 前端一键上线的工程要点
部署到 Cloudflare: 前端一键上线的工程要点
当 Vibe Coding 的最后一公里落到「让用户真的能打开那个 URL」时,部署平台的选择会直接决定上线后的体感。Cloudflare Pages 在这套课程里被反复用作「轻量 + 全球边缘」的默认落点,它的工程语义和 Vercel、Netlify 既有重叠又有差异。下面把它的核心要点拆成六件事:为什么选它、怎么构建 Next.js、环境变量怎么对齐、上线后立刻做的两件事、一键回滚的姿势、以及三家平台的取舍矩阵。
为什么是 Cloudflare Pages
Cloudflare Pages 的两个底层能力决定了它适合 Vibe Coding 产物:第一,全球边缘网络 (Edge Network)。Cloudflare 在六大洲数百个城市部署了 PoP(Point of Presence,边缘接入点),静态资源被缓存到离用户最近的节点,首屏 LCP(Largest Contentful Paint,最大内容绘制时长)往往能压到一秒以内。第二,Pages 是为静态托管 + Jamstack 而生 ,默认就对 Next.js、Astro、Hugo、Eleventy 等框架提供了一等公民支持。对个人开发者来说,这意味着拿到 Next.js 仓库后,只要接上 GitHub,后续的 git push 就是「一键上线」。
参考官方文档 Cloudflare Pages 与 Next.js,可以确认 Pages 的构建系统基于 Workers 的轻量容器,免费额度也覆盖了 Vibe Coding 小项目的体量。
Next.js 产物如何对接 Pages
Pages 对 Next.js 的支持有两种模式:一是原生框架支持(自动识别 create-next-app 脚手架),二是手动配置构建命令。课程默认采用第二种,目的是把控制权留在 wrangler.toml 或 Cloudflare 控制台的「Build command」字段里。
下面是典型的构建配置片段:
bash
# package.json
{
"scripts": {
"build": "next build",
"start": "next start",
"pages:build": "@cloudflare/next-on-pages build",
"preview": "next build && wrangler pages dev .vercel/output/static"
}
}
toml
# wrangler.toml 关键字段
name = "vibe-landing"
compatibility_date = "2024-09-01"
pages_build_output_dir = ".vercel/output/static"
compatibility_date 是 Cloudflare Workers 兼容版本的时间戳,用于把运行时锁到某一天的 Workers 能力集;pages_build_output_dir 告诉 Pages 去哪个目录取静态产物。Next.js 14+ 配合 @cloudflare/next-on-pages 会把产物输出到 .vercel/output/static,这与 Vercel 默认的 .next 是两套结构,这也是常被新手忽略的「跨平台产物路径」踩坑点。
环境变量与构建产物的对齐
环境变量是最容易踩坑的地方。Vibe Coding 项目里,Claude Code 通常通过 MCP GitHub connector 把 .env.local 排除在仓库外,但运行时还是会引用 NEXT_PUBLIC_* 这类公开环境变量。Pages 提供三个作用域:Build time (只在构建阶段注入)、Preview (预览部署)、Production (生产部署)。一个常见反模式是把 Stripe、Resend 等服务密钥当作 NEXT_PUBLIC_* 误推到客户端,导致密钥泄露。
| 变量作用域 | 注入时机 | 可见性 | 典型用途 |
|---|---|---|---|
| Build time | next build 期间 |
构建容器 + 客户端 bundle | NEXT_PUBLIC_SITE_URL |
| Preview | 预览分支构建 | 构建容器 + 客户端 | PREVIEW_API_KEY |
| Production | 生产部署构建 | 构建容器 + 客户端 | STRIPE_SECRET_KEY(严禁公开) |
对照上表,Pages 默认会把所有作用域的环境变量都暴露给构建容器,但只有 NEXT_PUBLIC_ 前缀的才会被 webpack/Turbopack 嵌入客户端 bundle。Claude Code 在 Plan 模式里通常会主动询问「这个变量需要客户端可见吗」,这正是把安全姿态编码进工作流的体现。
上线动作:暗色模式截图比对
部署完成的瞬间,第一件应该做的事不是发推特,而是立刻打开预览 URL,切到暗色模式并截图比对。Vibe Coding 阶段大量使用 Tailwind 的 dark: 前缀与 shadcn 主题变量,而 next-themes 在 SSR(服务器端渲染)与 hydration(客户端水合)之间存在一个经典时差:服务端先以 light 渲染,客户端再切到 dark,如果 CSS 变量加载顺序错位,会出现「闪屏」或「暗色回退到亮色」。把这个观察动作写成 QA 流程的硬性一步,可以避免「线上版本暗色失效」这种最难定位的回退。
工程师还容易忽略第二件动作:对比 Core Web Vitals。把 Vercel Analytics 或 Plausible 接入后,截图对比 INP / CLS 的变化趋势,任何超过 0.1 的突然跳变,都需要回到 Lighthouse 跑一次复现。
一键回滚的姿势
Pages 每次部署都会保留构建产物和 commit 绑定。在控制台「Deployments」列表里,任何历史版本都可以点「Rollback to this deploy」立即生效;也可以通过 Git 直接回退再 git push,触发新一轮构建。绑了 GitHub 之后,git revert <sha> 是最稳的回滚姿势 --- 它生成一个反向 commit,而不是 git reset 那种改写历史的危险动作,后者会让团队的 feature branch 出现无法 rebased 的孤儿 commit。
下面这张图描述了从本地构建到边缘节点再到用户浏览器的完整链路:

三家部署平台的取舍
Vibe Coding 的最后一公里不是单选题。下表给出 Vercel、Cloudflare Pages、Netlify 的关键差异,作为方案选型的取舍矩阵:
| 维度 | Vercel | Cloudflare Pages | Netlify |
|---|---|---|---|
| 边缘节点密度 | 中等 | 高(全球 300+ 节点) | 中等 |
| Next.js SSR 支持 | 一等公民 | 需适配(@cloudflare/next-on-pages) |
需适配 |
| 免费带宽 | 100 GB/月 | 无限带宽(限请求数) | 100 GB/月 |
| Git 集成 | 深度 | 标准 | 深度 |
| Functions 运行时 | Node.js / Edge | Workers / Pages Functions | Lambda 风格 |
vs 这三家平台,Cloudflare Pages 的优势在带宽成本与边缘节点密度,劣势在 Next.js 高级特性(Incremental Static Regeneration / ISR、Streaming SSR)的支持深度。如果你做的是 Landing Page + Markdown 博客为主、SSR 不重的 Vibe Coding 项目,Pages 是性价比最高的选择;一旦涉及复杂数据获取与缓存重验证,Vercel 的「零配置」优势就回来了。
典型踩坑清单:
pages_build_output_dir写错路径,导致部署后页面 404,但本地next dev仍然正常。NODE_VERSION没在 Pages 环境变量里固定,导致构建时拉到 major 升级的 Node.js,触发 esbuild 行为变化。- 把
.env.local误推到 GitHub,MCP GitHub connector 必须在装阶段就配置好.gitignore与 secret scanning。 - 暗色模式用
prefers-color-scheme而非class策略,与next-themes默认行为冲突。
工程师视角的最后一句
部署平台是 Vibe Coding 工程化的「水龙头」,它决定了 AI Coding Agent 写出来的代码多快能变成用户可触达的产物。Cloudflare Pages 通过「绑 Git + 一键回滚 + 边缘节点」三件套,把上线门槛压到了「git push」一句话。这套工作流的核心价值不在部署本身,而在于它把工程师从「运维工人」的角色里释放出来,让真正的工程注意力回到需求拆解与编排上,这也是 Vibe Coding 在工程师角色翻转这个维度上最直观的体感。
Vibe Coding 与传统开发的取舍矩阵
三种开发范式在这套 Vibe Coding 教程里反复出现:传统手写代码、纯 AI 一句话生成,以及 Vibe Coding 这种「自然语言驱动 + 工程师把关」的中间路线。它们不是简单的线性替代关系,而是在速度、质感、可维护性与学习成本四个维度上各有取舍。下面把这三条路径拆开,给出适用边界与不适合场景,并落到一张四维评分矩阵上,方便团队按项目特征对号入座。
传统手写:控制力强,周期最长
传统开发的逻辑起点是「工程师逐字符敲下每一行」。它的核心价值在控制力------命名、抽象边界、内存布局、错误分支、性能调优,每一步都是可解释、可回放的。这种姿势在两类场景几乎不可替代:强类型核心域(支付结算、订单履约、金融账务、医疗数据)和极致性能优化(毫秒级延迟敏感的实时通信、嵌入式资源受限环境、底层算法库)。在这些域里,任何抽象泄漏都会被系统放大,只有手动控制才能稳住。但代价是周期长:从需求拆解到首版可运行通常以周计,跨团队评审、PR(代码评审与合并请求)流程、测试覆盖、CI(持续集成)流水线层层叠加,首屏体验与交互细节往往被推迟到「打磨阶段」才能考虑,留给「好不好看」的预算非常有限。
纯 AI 生成:速度快,容易 AI Slop
另一极是「一句话让 AI 整页输出」。这种姿势在 Next.js + Tailwind CSS + shadcn/ui 这样的组合上尤为顺手,模型熟悉生态,能在数十秒内吐出可运行代码,完整参考可参见 Next.js 官方文档与 shadcn/ui 官方文档。但它的失败模式同样鲜明------讲师把它叫作 AI Slop,即「外观像、但缺乏质感的批量产出」:千篇一律的圆角、堆叠的阴影、模板化的文案、生硬的占位图、动效缺乏节奏感、按钮没有状态反馈、空状态永远是「No data」三个单词。它能跑,但它没有灵魂。要把这层「批量化感」压下去,工程师必须介入做审美判断,而这一步正是纯 AI 生成范式缺位的环节。
Vibe Coding:兼得速度与质感,但工程师必须懂审美
Vibe Coding 在两条极端之间折中:由 Claude Code 这类 AI Coding Agent 先按 Plan mode 出方案、再落到代码,工程师在 Review mode 做审美把关------色调、字阶、留白节奏、动效曲线、文案语气、信息密度。详细工作流可参考 Claude Code 官方文档。速度介于「手写一周」与「AI 一键出活」之间,但质感可显著高于纯 AI 输出。这套姿势把工程师的角色从「敲字符」翻转到「拆需求 + 编排工具 + 把关审美」,不再逐行写代码,而是逐轮对模型下指令、把模型产出向产品意图对齐。这也是为什么讲师把它定位为「零基础也能上手」------门槛不在语法,而在审美与产品判断。当 Agent 通过 MCP 官方协议或 GitHub MCP Server直接连上代码仓库后,工程师甚至不需要手动切窗口,所有改动都在一条对话流里闭环。

下表把三条路径在四个维度上做了对比,评分 1-5,数字越大越好(速度越快、质感越高、可维护性越强、学习成本越低)。
| 维度 | 传统手写 | 纯 AI 生成 | Vibe Coding |
|---|---|---|---|
| 速度(从需求到可演示) | 2 | 5 | 4 |
| 质感(交互与视觉完成度) | 5 | 2 | 4 |
| 可维护性(后续接手成本) | 5 | 2 | 3 |
| 学习成本(从零到首次上线) | 2 | 4 | 4 |
取舍矩阵告诉我们:Vibe Coding 不会在任意维度上击败对手,而是用「牺牲一点可维护性,换取速度和质感的兼顾」。这个权衡是否合算,取决于项目处于什么阶段、落在什么域。
适用的边界
四类场景 Vibe Coding 几乎总能打满价值:一是内部工具,使用人群少、迭代快、对代码寿命容忍度高;二是营销页,首屏的视觉与文案节奏决定转化率,反复重写成本极低;三是中后台,大量重复的表单页、表格页、列表页、详情页,适合用 MCP(Model Context Protocol,模型上下文协议)连接业务数据源后批量生成;四是早期 MVP(最小可行产品),核心目的是验证假设而非沉淀代码,迭代频率远高于维护频率。在这些域里,代码往往是「一次性、用完即弃」或者「三月后整体重写」,过度优化反而是负价值。
不适合的场景
三类场景需要谨慎,甚至要主动回到传统手写。第一是强类型核心域------支付链路、订单履约、金融账务、医疗数据处理,任何一行错位的字段都可能引发资金或合规风险,Vibe Coding 的「审美把关」不能替代类型系统与边界测试,TypeScript 的严格模式、Schema 校验、单元测试覆盖率在这里仍是硬约束。第二是复杂状态机------多分支工作流、分布式事务、回滚补偿、长流程编排,这类系统对状态不变量与转移路径有刚性约束,纯靠 prompt 难以稳定表达,需要明确的状态图与转换函数。第三是极致性能优化------Web Vitals 中的 INP(Interaction to Next Paint,交互到下一次绘制的延迟)、LCP(Largest Contentful Paint,最大内容绘制时间)、CLS(Cumulative Layout Shift,累积布局偏移)三项需要手动 profiling、内存分配策略、缓存命中率调优,这些动作无法一次性交给 LLM 完成。
踩坑清单与实战片段
下面是一段常见的 Vibe Coding 工作流伪代码,展示工程师如何在 Plan / Build / Review 闭环里和 Agent 配合:
bash
# 第一步:进入 Plan mode,先让 Agent 出方案
claude --plan "为营销页做一个 Hero 区块,主色调用墨绿+米白"
# 第二步:Review 方案,人工调整审美细节
# 审掉默认的 Tailwind 圆角,改用更克制的 2px
# 改字体层级,把副标题字阶压一档
# 第三步:Build,落地到 Next.js + shadcn/ui
claude --build
# 第四步:Review diff,逐文件确认改动面
gh pr review
这段循环的关键不在命令本身,而在第二步的「审美干预」------这是 Vibe Coding 区别于纯 AI 生成的核心动作。把它省略掉,产出就会滑向 AI Slop;把它做充分,产出就能逼近手工打磨的质感,却只需要后者十分之一的时间。
观察 把「审美能力」当作 Vibe Coding 工程师的核心素养,反而让这个范式比传统开发更适合跨职能协作。产品经理可以更早介入,因为反馈循环不再以「代码量」为单位;设计师可以直接拉曲线,因为模型的迭代成本接近于零。这种协作形态会让团队角色边界重新洗牌------但前提是工程师愿意放下「我写代码」的身份,转向「我判断代码」。这也是讲师反复强调的「角色翻转」:工具越强,人的判断越值钱。
数据 从讲师给出的工程对比看,一个标准营销页在传统手写下首次上线大约需要 3-5 天,纯 AI 生成可在 10-20 分钟内跑出可演示版本,Vibe Coding 在「审美把关一步到位」的前提下落在 1-3 小时区间。可维护性方面,传统手写得分 5(任意接手者都能沿原意继续)、纯 AI 生成得分 2(缺少抽象,直接接管成本极高)、Vibe Coding 得分 3(工程师参与了关键决策,留下了审美与结构的痕迹,后续接手仍需重新对齐)。学习成本一项,纯 AI 生成最低,但它的失败率也最高;Vibe Coding 在「审美 + Agent 操作」两个新增维度上拉高了上手门槛,因此学习成本略高于纯 AI 生成,但仍远低于传统手写。
落到团队决策上,这四条曲线交叉的位置就是 Vibe Coding 的甜蜜点:周期短于一周、用户能直接看到效果、代码寿命短于半年、对质感有要求但不要求极致性能。一旦项目越出这个区域,要么退回传统手写换可维护性,要么让位给纯 AI 生成换吞吐量。Vibe Coding 不是银弹,而是一把定位清晰的工具,选对了场景,它能把团队从「写代码」里解放出来,把精力投到更值得投的地方------产品意图、用户反馈、迭代节奏。
进阶路线: Vibe Coding 工程师的能力栈与生态
当 Vibe Coding 从「能跑」走向「能维护、能协作、能贡献」时,工程师需要的不再只是敲下一句自然语言提示,而是一套可叠加的能力组合。把这套组合拆开看,至少由四根支柱组成:提示工程、设计素养、Git 工作流、Skill 编写。每一根都不是孤立的技术点,而是后续在团队里承担更大责任的入场券。
提示工程 是离工程师最近的入口。看似只是「写得清楚」,实际上包含意图拆解、上下文组织、约束条件显式化三个层次。一个好提示要让 Agent 在第一次执行时就知道该读哪些文件、写哪些字段、避开哪些反模式。Anthropic 在 Claude Code 文档(docs.anthropic.com/en/docs/cla...%25E4%25B8%25AD%25E6%2598%258E%25E7%25A1%25AE%25E6%258A%258A "https://docs.anthropic.com/en/docs/claude-code/overview)%E4%B8%AD%E6%98%8E%E7%A1%AE%E6%8A%8A") Slash Commands(docs.anthropic.com/en/docs/cla...%25E4%25BD%259C%25E4%25B8%25BA%25E5%258F%25AF%25E5%25A4%258D%25E7%2594%25A8%25E6%258F%2590%25E7%25A4%25BA%25E6%25A8%25A1%25E6%259D%25BF%25E6%259C%25BA%25E5%2588%25B6%2C%25E8%25BF%2599%25E6%25AD%25A3%25E6%2598%25AF%25E6%258A%258A%25E9%259B%25B6%25E6%2595%25A3%25E6%258F%2590%25E7%25A4%25BA%25E6%25B2%2589%25E6%25B7%2580%25E6%2588%2590%25E5%259B%25A2%25E9%2598%259F%25E8%25B5%2584%25E4%25BA%25A7%25E7%259A%2584%25E7%25AC%25AC%25E4%25B8%2580%25E6%25AD%25A5%25E3%2580%2582%25E6%258F%2590%25E7%25A4%25BA%25E5%25B7%25A5%25E7%25A8%258B%25E7%259A%2584%25E6%2588%2590%25E7%2586%259F%25E5%25BA%25A6%2C%25E7%259B%25B4%25E6%258E%25A5%25E5%2586%25B3%25E5%25AE%259A%25E4%25BA%2586%25E4%25B8%258B%25E6%25B8%25B8 "https://docs.anthropic.com/en/docs/claude-code/slash-commands)%E4%BD%9C%E4%B8%BA%E5%8F%AF%E5%A4%8D%E7%94%A8%E6%8F%90%E7%A4%BA%E6%A8%A1%E6%9D%BF%E6%9C%BA%E5%88%B6,%E8%BF%99%E6%AD%A3%E6%98%AF%E6%8A%8A%E9%9B%B6%E6%95%A3%E6%8F%90%E7%A4%BA%E6%B2%89%E6%B7%80%E6%88%90%E5%9B%A2%E9%98%9F%E8%B5%84%E4%BA%A7%E7%9A%84%E7%AC%AC%E4%B8%80%E6%AD%A5%E3%80%82%E6%8F%90%E7%A4%BA%E5%B7%A5%E7%A8%8B%E7%9A%84%E6%88%90%E7%86%9F%E5%BA%A6,%E7%9B%B4%E6%8E%A5%E5%86%B3%E5%AE%9A%E4%BA%86%E4%B8%8B%E6%B8%B8") Agent 输出的稳定性。
设计素养 决定了 Vibe Coding 产物的天花板。Next.js、Tailwind CSS、shadcn/ui 的组合(对应官方文档 nextjs.org/docs、https:...%25E6%258A%258A%25E8%25A7%2586%25E8%25A7%2589%25E4%25B8%2580%25E8%2587%25B4%25E6%2580%25A7%25E4%25B8%258B%25E6%2594%25BE%25E5%2588%25B0%25E4%25BA%2586 "https://nextjs.org/docs、https://tailwindcss.com/docs、https://ui.shadcn.com/docs)%E6%8A%8A%E8%A7%86%E8%A7%89%E4%B8%80%E8%87%B4%E6%80%A7%E4%B8%8B%E6%94%BE%E5%88%B0%E4%BA%86") token 级别。工程师只要读懂设计意图,就能让 Agent 输出在视觉上不像「AI 写的页面」。否则再聪明的 Agent,产物仍会显得廉价,因为它缺的不是写代码的能力,而是审美判断的能力。
Git 工作流 是 Vibe Coding 与团队协作的桥梁。Plan → Build → Review 的闭环之所以能跑通,正是因为每一步都对应一个 commit、一条分支、一次 PR。GitHub MCP(详见 github.com/modelcontex...%25E8%25AE%25A9 "https://github.com/modelcontextprotocol/servers)%E8%AE%A9") Agent 直接读写仓库,工程师必须理解 PR review、branch 策略、commit message 规范,否则 Agent 的「自动提交」会迅速污染主干。换句话说,Git 工作流不是「可选项」,而是「Agent 输出能否被团队接受」的过滤器。
Skill 编写 是把个人经验封装成可复用资产的关键。一个 Skill 本质上是结构化提示 + 工具调用约定 + 验收标准,对应仓库里的 Markdown 文件。能写出好 Skill 的人,本质上是把团队的最佳实践文档化了,而文档化正是规模化的前提。
生态地图:三件套的边界
把 Claude Code、OpenAI Codex、MCP 协议摆在一起看,会发现它们并非简单的「同质竞品」,而是在能力栈上彼此互补。下表给出一个简化的边界对照:
| 工具 / 协议 | 核心定位 | 擅长场景 | 主要局限 |
|---|---|---|---|
| Claude Code | 终端型 Coding Agent | 长链路任务、Plan/Build/Review 闭环 | 受限于本地终端环境 |
| OpenAI Codex | IDE / CLI 双形态 | 代码补全、多文件重构 | 与外部系统对接偏弱 |
| MCP 协议 | 工具接入开放标准 | 让任意 Agent 接入 GitHub / DB / CMS | 需要自行部署或选择 MCP server |
Codex 文档(developers.openai.com/codex)给出了%25E7%25BB%2599%25E5%2587%25BA%25E4%25BA%2586 "https://developers.openai.com/codex)%E7%BB%99%E5%87%BA%E4%BA%86") IDE 与 CLI 双端的工作流,Model Context Protocol 官网(modelcontextprotocol.io/)则把%25E5%2588%2599%25E6%258A%258A "https://modelcontextprotocol.io/)%E5%88%99%E6%8A%8A") MCP 定义为「Agent ↔ 工具」之间的开放协议。Claude Code 通过 Connectors 暴露 MCP,Codex 通过插件机制接入,二者对 MCP 的支持深度决定了生态延展性。
取舍上,如果项目只在本机跑单文件脚本,Codex 更轻;一旦涉及仓库、CI、部署流水线,Claude Code + MCP 的组合更省心。vs 一味比较模型跑分,识别自己工作流的真正瓶颈更值得工程师花时间。这不是「谁更强」的问题,而是「你的上下文边界在哪」的问题。
提示可沉淀资产:三件可复用的工程产物
Vibe Coding 最容易被低估的价值,是「提示本身可以变成版本化资产」。一个团队如果在以下三个方向做沉淀,半年后回头看会显著领先于临时起意的对手。
自定义 Skill:在 Claude Code 中,每个 Skill 是一个 Markdown 文件,定义触发条件、工具调用与输出契约。当团队反复出现「Hero 区块」「Pricing 表」等需求时,把对应提示沉淀成 Skill,后续所有人调用同一份 Skill,产出自然趋同,review 成本也骤降。
Design Token 库 :Tailwind 的 config、CSS 变量、shadcn 主题文件共同构成设计 token。把颜色、间距、字体、阴影集中到 tokens.css 或 tailwind.config.ts,Agent 在写样式时只要引用 token,就不会出现「每个 PR 一个色板」的情况。设计 token 既是视觉一致性的护栏,也是 Agent 的「视觉宪法」。
Storyboard 模板:复杂页面不止一个组件,而是一组组件按时间顺序登场。把「Hero → Features → Pricing → FAQ → Footer」这类结构沉淀成 Storyboard 模板,Agent 只要按模板填字段,产出节奏就不会失控,信息密度也不会失衡。
这三类资产的共同特征是:可 diff、可 review、可回滚。这正是它们区别于「群里发一句提示」的关键------资产必须能在 Git 里被管理,否则就不算资产,只算聊天记录。
从使用者到贡献者
工程师的进阶路径,在 Agent 时代出现了一条清晰的曲线:使用者 → 高级使用者 → 内部贡献者 → 框架贡献者。每一档对应的不是「会用更多工具」,而是「影响半径」的扩大。
- 使用者:跑通 Plan → Build → Review,产出可上线页面;关注点在「让 Agent 跑起来」。
- 高级使用者:能写出可复用的 Skill,把个人经验沉淀到团队仓库;关注点在「让团队少踩坑」。
- 内部贡献者:在自家代码库里维护一套 Design Token + Storyboard + Skill 三件套,并把最佳实践写成内部 RFC(Request for Comments,内部提案);关注点在「让流程可规模化」。
- 框架贡献者:向 Claude Code、Codex、MCP server 的开源仓库提交 PR,影响上游行为;关注点在「让生态变得更好用」。
这条路线的入场券很朴素:先用熟,再读 diff,最后提 PR 。GitHub MCP Server 仓库(github.com/modelcontex...%25E6%2598%25AF%25E4%25B8%2580%25E4%25B8%25AA%25E9%2580%2582%25E5%2590%2588%25E8%25B5%25B7%25E6%25AD%25A5%25E7%259A%2584%25E5%2585%25A5%25E5%258F%25A3%3A%25E5%25AE%2583%25E7%259A%2584 "https://github.com/modelcontextprotocol/servers)%E6%98%AF%E4%B8%80%E4%B8%AA%E9%80%82%E5%90%88%E8%B5%B7%E6%AD%A5%E7%9A%84%E5%85%A5%E5%8F%A3:%E5%AE%83%E7%9A%84") issue 区对新人不算苛刻,文档结构清晰,改一个 connector 字段就能完成一次有效 PR。从「读别人代码」到「改一个文件」再到「合入主干」,这是工程师把外部杠杆变成自身杠杆的最小闭环。
代码示例:从安装到 Skill 调用的最小闭环
下面这段 bash 片段展示了一个进阶工程师常用的「自检 → 拉取 Skill → 触发构建」三步:
bash
# 1. 自检 Agent 环境
claude doctor
# 2. 从团队仓库同步最新 Skill 集合
git pull origin main && ls .claude/skills/
# 3. 在指定 Skill 下让 Agent 跑一次构建
claude --skill landing-hero \
--input "title=AI 工程师入门,subtitle=从零到上线" \
--output app/(marketing)/page.tsx
这段命令把「环境校验、资产同步、Skill 调用」三件事压在一个 shell 流程里,既是进阶工作流的样板,也是团队 CI(持续集成)可以借鉴的最小单元。

工程师角色的翻转
观察 当工程师把「敲代码」这件事交给 Agent 之后,真正稀缺的能力反而是「判断该让 Agent 做什么、做到什么程度为止」。一个高级 Vibe Coding 工程师的工作清单里,代码本身可能只占两成,其余八成是需求拆解、提示设计、Skill 维护、PR review、安全审计。这种从「打字员」到「指挥家」的角色翻转,意味着工程师的核心竞争力正在从「写得快」迁移到「看得准、写得清、审得严」。换句话说,Agent 越强,工程师越要回到「人」的判断上。
数据 从这套课程的实操样本看,一个零基础工程师在首次完成 Vibe Coding 全流程时,大约 70% 的时间花在「需求澄清 + Plan 评审」上,只有 30% 真正用于 Build 与 Review。这与「传统手写」时代的「90% 编码 + 10% 思考」形成鲜明对比。换言之,提示工程与设计素养的边际收益,在 Vibe Coding 里第一次超过了代码本身的边际收益------这是工程师必须重新分配学习预算的根本原因。
把这套能力栈和生态地图合起来看,进阶路径其实只有一句话:先把 Agent 用稳,再把经验沉淀成 Skill 与 Token,最后把改进回送给上游框架。Vibe Coding 的终点不是「让 AI 写代码」,而是「让工程师有能力指挥一支 AI 乐队」。
参考来源
官方与一手资料
- Anthropic 官方文档 docs.anthropic.com
- Claude Code 文档 docs.anthropic.com/en/docs/cla...
- Claude Code Slash Commands 文档 docs.anthropic.com/en/docs/cla...
- Model Context Protocol 官方文档 modelcontextprotocol.io/
- Anthropic MCP 官方介绍 www.anthropic.com/news/model-...
- OpenAI API 参考 platform.openai.com/docs
- OpenAI Codex 文档 developers.openai.com/codex
- Cursor 官方文档 docs.cursor.com
- GitHub Copilot 文档 docs.github.com/en/copilot
- Next.js 官方文档 nextjs.org/docs
- Tailwind CSS 官方文档 tailwindcss.com/docs
- shadcn/ui 官方文档 ui.shadcn.com/docs
- Vercel 文档 vercel.com/docs
- Cloudflare Pages 文档 developers.cloudflare.com/pages
- Netlify 文档 docs.netlify.com
- GitHub MCP Server 仓库 github.com/modelcontex...
- GitHub Actions 文档 docs.github.com/en/actions
- GitHub Personal Access Token 文档 docs.github.com/en/authenti...
- Let's Encrypt 官方 letsencrypt.org/
- Cloudflare DNS 文档 developers.cloudflare.com/dns
- Sentry 文档 docs.sentry.io
- Plausible Analytics 文档 plausible.io/docs
- Playwright 文档 playwright.dev/docs/intro
- Vitest 文档 vitest.dev/guide/
- Dependabot 文档 docs.github.com/en/code-sec...
- Web Vitals 文档 web.dev/vitals/
- TechWithTim 频道 www.youtube.com/@TechWithTi...