实战案例:从零构建高级 Todo 应用
一个 Superpowers 新手可以构建一个完整的 Todo 应用——从头脑风暴到运行测试——仅在一次工作会话中完成。这是体验完整工作流程的理想入门案例。
背景
你想构建一个 Todo 应用作为 prototype/demo——足够令人印象深刻可以展示,但使用 Superpowers 工作流程从头到尾构建。
需求:
- CRUD:添加、编辑、删除、标记完成
- 按状态、优先级、分类进行筛选/搜索
- 分类(Work / Personal / Study)和优先级(High / Medium / Low)
- 拖拽排序
- 每个 todo 设置截止日期
- 暗色模式(手动切换 + 跟随系统偏好)
- 数据存储在 localStorage(不需要后端)
技术栈:
- Vite + React 18 + TypeScript
- shadcn/ui + Tailwind CSS
- @dnd-kit(拖拽)
- date-fns(日期处理)
- Vitest + React Testing Library
你将学到什么
在本教程中,你将应用 Superpowers 的四个核心技能:
- Brainstorming & Design -- 通过问答探索需求,比较方案,用 visual companion 选择布局
- Writing Plans -- 拆分为 11 个有明确验证标准的任务
- TDD -- 先为 hook 和组件编写测试
- Debugging & Verification -- 处理实际兼容性问题并验证一切正常运行
最终目标:一个功能完整的 Todo 应用,12 个测试用例全部通过,production 构建成功,按照有纪律的工作流程构建。
分步实践
步骤 1:头脑风暴 Todo App 设计
你打开与 AI 的对话并说:
"我想用 React + TypeScript 构建一个简单的 Todo 应用。在写代码之前先进行头脑风暴。"
AI 进入头脑风暴模式,启动 visual companion(在浏览器上显示 mockup),然后逐个提问:
问题 1: "这个 Todo 应用的主要目的是什么?"
- A) 学习项目/作品集
- B) 个人日常使用的应用
- C) Prototype/demo 用于展示
你选择:C) Prototype/demo -- 展示时需要令人印象深刻。
问题 2: "应用需要哪些功能?"
- A) 基础 -- 添加、编辑、删除、标记完成
- B) 中等 -- 在 A 的基础上加筛选/搜索、分类、优先级
- C) 高级 -- 在 B 的基础上加拖拽、截止日期、暗色模式、localStorage 持久化
你选择:C) 高级 -- demo 需要功能齐全。
问题 3: "数据存储在哪里?"
- A) 仅 LocalStorage
- B) Mock API(json-server 或 MSW)
- C) 真实后端(Firebase/Supabase)
你选择:A) LocalStorage -- 简单,不需要后端。
问题 4: "UI/样式用什么方案?"
- A) Tailwind CSS
- B) shadcn/ui + Tailwind
- C) CSS Modules / Styled Components
- D) Ant Design / MUI
你选择:B) shadcn/ui + Tailwind -- 组件美观、专业、易于定制。
问题 5: "工具链/构建用什么?"
- A) Vite
- B) Next.js
- C) Create React App
你选择:A) Vite -- 快速、轻量、最流行。
收集完足够信息后,AI 展示 3 种方案:
## 方案 A:Single Page — All-in-One(推荐)
整个应用在 1 个页面中。侧边栏包含筛选/分类,主区域包含 todo 列表。
- 优点:简单,不需要路由,UX 流畅
- 缺点:所有内容集中在 1 个视图
## 方案 B:Multi-Page 使用 React Router
分成多个页面:Dashboard、Todo List、Settings。
- 优点:结构清晰,易于扩展
- 缺点:对 todo 应用来说过度设计,增加依赖
## 方案 C:Kanban Board 风格
Todo 以列形式显示(To Do / In Progress / Done),在列之间拖拽。
- 优点:演示时视觉效果令人印象深刻
- 缺点:复杂度高很多,难以筛选/排序
你最初选择了 Kanban(C),但在 visual companion 上查看 mockup 后,你改选了 方案 A:Single Page -- 在功能和复杂度之间取得了最佳平衡。
AI 继续询问布局:
- A) Sidebar + Main Content(类似 Todoist)
- B) Top Filter Bar + Centered List(极简风格)
你选择:B) Top Filter Bar + Centered List -- 简洁极简。
AI 编写了详细的设计规格,包含 3 个部分:
DESIGN SPEC: Todo App
=== Section 1: Architecture & Data Model ===
Data Model:
interface Todo {
id: string
title: string
completed: boolean
priority: 'high' | 'medium' | 'low'
category: 'Work' | 'Personal' | 'Study'
dueDate: string | null
order: number
createdAt: string
}
State Management:
- useReducer 管理 todo 状态(add, edit, delete, toggle, reorder)
- 自定义 hook useTodos() — 处理逻辑 + localStorage 同步
- 自定义 hook useTheme() — 暗色/亮色模式切换
Component Structure:
App
├── Header(标题、统计、暗色模式切换)
├── FilterBar(状态筛选、优先级筛选、分类筛选、搜索)
├── TodoInput(添加新 todo 表单 — 点击展开)
├── TodoList(DnD 容器)
│ └── TodoItem[](复选框、标题、优先级徽章、分类、截止日期、操作)
└── EditTodoDialog(shadcn dialog)
=== Section 2: UI Components & Interactions ===
FilterBar:
- 水平排列的 Pill 按钮:Status (All|Active|Done) | Priority | Category
- 使用 AND 组合(Active + High + Work → 只显示满足所有条件的 todo)
- 搜索输入框在右侧
TodoItem:
- Checkbox | Title | Priority 徽章(彩色)| Category 标签 | Due date | Menu (⋮)
- Hover → 左侧显示拖拽手柄
- Completed → 变淡 + 删除线
- Overdue → 截止日期显示红色
Drag & Drop:
- @dnd-kit/sortable 实现拖拽排序
- 在筛选视图中拖拽时,只更新相对顺序;
被筛选隐藏的项目保持原始顺序
=== Section 3: Dark Mode & Persistence ===
Dark Mode: Tailwind dark: class + 默认跟随系统偏好
localStorage: 写入时 300ms 防抖,无效数据时回退为空数组
Testing: Vitest + RTL 测试 useTodos hook、TodoInput、TodoItem
AI 分派 spec reviewer 检查规格质量。Reviewer 批准并提出 3 个小建议(已更新到规格中)。
你批准了。进入下一个阶段。
Superpowers 提示: 设计规格保存在
docs/superpowers/specs/中,spec reviewer 在转入编写计划之前自动检查。详见 Brainstorming。
步骤 2:Superpowers 编写详细计划
基于设计规格,AI 将工作拆分为 11 个任务(比简单应用多很多):
## Plan: Todo App
### Task 1: Project Scaffold
- Vite + React + TS, Tailwind, shadcn/ui, @dnd-kit, date-fns
- Vitest + React Testing Library
- Verification: npm run build 成功
### Task 2: Types & Storage Utilities
- src/types/todo.ts — interface Todo, Filters, constants
- src/lib/storage.ts — localStorage helpers
- Verification: TypeScript compile OK
### Task 3: useTodos Hook (TDD)
- 先写测试: src/hooks/use-todos.test.ts
- 编写代码: src/hooks/use-todos.ts
- Verification: 6/6 tests pass
### Task 4: Filter Logic & useTheme Hook
- src/lib/filters.ts — applyFilters() function
- src/hooks/use-theme.ts — 暗色模式切换
### Task 5: Header & FilterBar Components
- src/components/header.tsx
- src/components/filter-bar.tsx
### Task 6: TodoInput Component (TDD)
- 先写测试: src/components/todo-input.test.tsx
- 编写代码: src/components/todo-input.tsx
- Verification: 3/3 tests pass
### Task 7: TodoItem Component (TDD)
- 先写测试: src/components/todo-item.test.tsx(需要 DndContext wrapper)
- 编写代码: src/components/todo-item.tsx
- Verification: 3/3 tests pass
### Task 8: TodoList + Drag & Drop
- src/components/todo-list.tsx
### Task 9: EditTodoDialog
- src/components/edit-todo-dialog.tsx
### Task 10: Assemble App + Toast
- 将所有组件连接到 App.tsx
- Verification: npm run build 成功
### Task 11: Final Polish & All Tests
- Verification: 12/12 tests pass, tsc --noEmit OK, build OK
AI 分派 plan reviewer 检查。Reviewer 发现 2 个问题:
- TodoItem 测试缺少 DndContext wrapper --
useSortable需要DndContextprovider,测试会失败 - Sonner 在 Task 1 中未安装 -- 在 Task 10 会导致报错
AI 在开始实现之前修复了这两个问题。
Superpowers 提示: 计划保存在
docs/superpowers/plans/中,在执行前自动审查。详见 Writing Plans。
你确认:"OK,开始实现。"
步骤 3:按计划实现(TDD:RED → GREEN → REFACTOR)
AI 按计划逐个执行任务。有测试的任务都遵循 TDD 循环。
Task 1: Project Scaffold
搭建 Vite + React + TS,安装所有依赖。遇到实际问题:
- Vite 8 不兼容
@tailwindcss/vite→ 使用--legacy-peer-deps - shadcn/ui init 失败 因为缺少 import alias → 在 tsconfig + vite.config 中配置
@/alias - Vite 8 与 shadcn 冲突 → 降级到 Vite 7
实际经验: 脚手架搭建并不总是一帆风顺。库之间的兼容性问题很常见。重要的是知道如何调试和找到变通方案。
Task 2: Types & Storage Utilities
| 文件 | 描述 |
|---|---|
src/types/todo.ts | Interface Todo, Filters, type aliases, constants (PRIORITIES, CATEGORIES) |
src/lib/storage.ts | loadTodos(), saveTodos(), loadTheme(), saveTheme() 带错误处理 |
Task 3: useTodos Hook (TDD)
| 文件 | 描述 | |
|---|---|---|
| 测试 | src/hooks/use-todos.test.ts | 6 个测试用例:starts empty, add todo, toggle todo, delete todo, edit todo, reorder todos |
| 代码 | src/hooks/use-todos.ts | useReducer + localStorage 同步,暴露:addTodo, toggleTodo, deleteTodo, editTodo, reorderTodos |
RED → npx vitest run → FAIL(文件不存在)→ GREEN → 实现 hook → 6/6 PASS
Task 4: Filter Logic & useTheme
| 文件 | 描述 |
|---|---|
src/lib/filters.ts | applyFilters() -- 对 status、priority、category、search 进行 AND 组合筛选 |
src/hooks/use-theme.ts | 暗色/亮色切换,同步 localStorage + 系统偏好 |
Task 5: Header & FilterBar
| 文件 | 描述 |
|---|---|
src/components/header.tsx | 应用名称、统计计数器、暗色模式切换(Sun/Moon 图标) |
src/components/filter-bar.tsx | 状态/优先级/分类的 Pill 按钮 + 搜索输入框 |
Task 6: TodoInput (TDD)
| 文件 | 描述 | |
|---|---|---|
| 测试 | src/components/todo-input.test.tsx | 3 个测试用例:render placeholder, call onAdd on submit, clear input after submit |
| 代码 | src/components/todo-input.tsx | 输入框展开为表单:title, priority dropdown, category dropdown, date picker |
RED → FAIL → GREEN → 3/3 PASS
Task 7: TodoItem (TDD)
| 文件 | 描述 | |
|---|---|---|
| 测试 | src/components/todo-item.test.tsx | 3 个测试用例:render title + priority, toggle checkbox, line-through when completed。注意: 测试需要 DndContext + SortableContext wrapper |
| 代码 | src/components/todo-item.tsx | 带拖拽手柄的 Sortable 项目,checkbox, priority 徽章, category 标签, due date, dropdown menu |
RED → FAIL → GREEN → 3/3 PASS
Task 8-9: TodoList + EditTodoDialog
| 文件 | 描述 |
|---|---|
src/components/todo-list.tsx | 使用 @dnd-kit/core + @dnd-kit/sortable 的 DnD 容器,空状态 |
src/components/edit-todo-dialog.tsx | shadcn Dialog 带编辑表单:title, priority, category, date picker |
Task 10: Assemble App
将所有内容连接到 App.tsx:useTodos + useTheme + applyFilters + Toaster。Production 构建成功。
Task 11: Final Polish
运行 tsc --noEmit 通过,但 npm run build 发现 TypeScript 错误 asChild prop -- shadcn v2 使用 base-ui 替代 radix,需要改用 render prop。修复后 → 构建成功,12/12 测试通过。
每个任务的 TDD 流程: AI 先写测试 → 运行测试确认 FAIL → 实现最小代码 → 运行测试确认 PASS → 需要时重构 → 提交。详见 TDD。
步骤 4:Verification -- 全面验证
所有 11 个任务已完成。运行最终验证。
运行完整测试套件
npx vitest run
✓ src/hooks/use-todos.test.ts (6 tests)
✓ useTodos > starts with empty todos
✓ useTodos > adds a todo
✓ useTodos > toggles a todo
✓ useTodos > deletes a todo
✓ useTodos > edits a todo
✓ useTodos > reorders todos
✓ src/components/todo-input.test.tsx (3 tests)
✓ TodoInput > renders placeholder input
✓ TodoInput > calls onAdd with todo data on submit
✓ TodoInput > clears input after submit
✓ src/components/todo-item.test.tsx (3 tests)
✓ TodoItem > renders todo title and priority
✓ TodoItem > calls onToggle when checkbox clicked
✓ TodoItem > shows line-through when completed
Test Files 3 passed (3)
Tests 12 passed (12)
类型检查和构建
npx tsc --noEmit # No errors
npm run build # 构建成功
声明
Todo App 完成。12/12 测试通过。Production 构建 OK。无 TypeScript 错误。10 个干净的按功能划分的提交。
结果
完成整个流程后,你拥有:
完整功能:
- CRUD todos(添加、编辑、删除、切换完成状态)
- AND 组合筛选(status、priority、category + search)
- 拖拽排序
- 截止日期带逾期警告(红色)
- 暗色模式(手动切换 + 跟随系统偏好)
- localStorage 持久化(300ms 防抖)
- 响应式、极简 UI,使用 shadcn/ui
- 显示统计信息(总任务、活跃、已完成)
12 个测试用例 100% 通过 覆盖:
- 自定义 hook
useTodos:add, toggle, delete, edit, reorder, empty state - 组件
TodoInput:render, submit, clear - 组件
TodoItem:render, toggle, completed style
文件结构:
src/
App.tsx
index.css
test-setup.ts
types/
todo.ts
lib/
storage.ts
filters.ts
utils.ts
hooks/
use-todos.ts
use-todos.test.ts
use-theme.ts
components/
header.tsx
filter-bar.tsx
todo-input.tsx
todo-input.test.tsx
todo-item.tsx
todo-item.test.tsx
todo-list.tsx
edit-todo-dialog.tsx
ui/ (shadcn components)
实际遇到的问题
与理想化的教程不同,实际工作会话遇到了许多需要处理的问题:
1. Vite 8 与 Tailwind 插件不兼容
@tailwindcss/vite 尚未支持 Vite 8 → 使用 --legacy-peer-deps 安装,之后当 shadcn 也冲突时降级到 Vite 7。
2. shadcn/ui init 因缺少 import alias 失败
shadcn 要求 @/ import alias → 必须在 tsconfig 中配置 baseUrl + paths,在 vite.config 中配置 resolve.alias。
3. shadcn v2 使用 base-ui 替代 radix
asChild prop 不再有效 → 必须改用 render prop 用于 PopoverTrigger 和 DropdownMenuTrigger。这个错误仅在运行 npm run build 时出现(vite build 有自己的类型检查),tsc --noEmit 反而通过了,dev 模式也不报错。
4. TodoItem 测试需要 DnD wrapper
useSortable hook 要求 DndContext + SortableContext provider。不 wrap 的话测试会崩溃。Plan reviewer 在实现之前就发现并修复了这个问题。
经验: 这就是验证环节至关重要的原因。许多错误只在 production 构建或严格类型检查时才会出现,在 dev 模式下看不到。
关键要点
1. 头脑风暴帮你在正确的时机改变想法
你最初选择了 Kanban Board,但在 visual companion 上查看 mockup 后,你意识到 Single Page 更合适。在头脑风暴阶段改变想法花费 0 行代码。在实现之后改变则需要数小时的重构。
2. Plan reviewer 在写代码之前就捕获了 bug
Reviewer 在计划中发现了 2 个问题(测试中缺少 DndContext wrapper、缺少 sonner 依赖)。如果不进行审查,这些 bug 会在实现过程中出现,浪费调试时间。
3. 兼容性问题是常态
11 个任务中有 3 个遇到了兼容性问题(Vite 8、shadcn alias、asChild prop)。这不是你的 bug -- 这是 JavaScript 生态系统的现实。工作流程帮你快速发现和修复,而不是手忙脚乱。
4. useReducer + Custom Hook + TDD 是强大的组合
useTodos hook 封装了全部逻辑(CRUD、reorder、localStorage sync)并有 6 个测试用例保护。当 UI 变得复杂(拖拽、筛选、编辑对话框)时,逻辑依然稳定,因为已经独立测试过了。
5. 11 个任务但每个都小而清晰
"构建高级 Todo 应用"听起来很吓人。但当拆分成 11 个任务时,每个任务只创建 1-2 个文件并有自己的验证标准。你永远不需要在脑中记住整个应用 -- 只需专注于当前任务。
6. 这是实际项目的跳板
这个"高级"Todo 应用已经包含了:自定义 hooks、拖拽、暗色模式、shadcn/ui、localStorage 持久化、TDD、自动审查。这些都是你在所有 React 项目中都会复用的模式。
现实不像教程那样完美。 你会遇到兼容性问题、库的变更和意外错误。Superpowers 工作流程不会消除这些问题 -- 它帮你尽早发现并系统性地处理,而不是不知从何下手地手忙脚乱。