7.2 搭建 MVP:从零到能跑
上一节我们写好了 PRD,这一节开始真正写代码。
别紧张。你不需要从零手写每一行代码。我们的策略是:用 AI 当你的结对编程伙伴,你负责方向,AI 负责实现。
第一步:初始化项目
打开终端,运行:
npx create-next-app@latest daily-focus --typescript --tailwind --eslint --app --src-dir --import-alias "@/*"
这个命令会问你几个问题,一路回车就行。它帮你创建一个 Next.js 项目,自带 TypeScript 和 Tailwind CSS。
创建完后进入项目目录:
cd daily-focus
npm run dev
打开浏览器访问 http://localhost:3000,你会看到 Next.js 的默认页面。
恭喜,你的项目已经能跑了。 虽然现在什么功能都没有,但它已经能跑了——这是最重要的一步。
第二步:创建主页面
现在,打开你的 AI 编程工具(Claude Code 或 Cursor),输入第一个 prompt:
我正在做一个叫"AI 每日聚焦助手"的 Web 应用。
请帮我修改 src/app/page.tsx,创建主页面,要求如下:
1. 页面标题"🎯 AI 每日聚焦助手"
2. 副标题"每天聚焦 3 件最重要的事"
3. 三个输入框,placeholder 分别是"今天最重要的事 #1""#2""#3"
4. 一个保存按钮
5. 用 Tailwind CSS 样式,简洁现代风格,居中布局
用 React useState 管理输入状态。
AI 会生成类似这样的代码:
"use client";
import { useState } from "react";
export default function Home() {
const [tasks, setTasks] = useState(["", "", ""]);
const handleChange = (index: number, value: string) => {
const newTasks = [...tasks];
newTasks[index] = value;
setTasks(newTasks);
};
return (
<main className="min-h-screen flex items-center justify-center bg-gradient-to-b from-orange-50 to-white">
<div className="max-w-md w-full px-6 py-10">
<h1 className="text-3xl font-bold text-center text-orange-600">
🎯 AI 每日聚焦助手
</h1>
<p className="text-center text-gray-500 mt-2 mb-8">
每天聚焦 3 件最重要的事
</p>
<div className="space-y-4">
{tasks.map((task, index) => (
<input
key={index}
type="text"
value={task}
onChange={(e) => handleChange(index, e.target.value)}
placeholder={`今天最重要的事 #${index + 1}`}
className="w-full px-4 py-3 border border-gray-200 rounded-xl
focus:outline-none focus:ring-2 focus:ring-orange-300
text-gray-700"
/>
))}
</div>
<button className="w-full mt-6 bg-orange-500 text-white py-3 rounded-xl
hover:bg-orange-600 transition font-medium">
保存今日聚焦
</button>
</div>
</main>
);
}
保存文件,刷新浏览器。你应该能看到一个漂亮的橙色主题页面,有三个输入框和一个按钮。
遇到报错怎么办
如果你看到红色错误信息,先看两个地方:
- 终端——看有没有编译错误
- 浏览器控制台——按 F12 打开开发者工具
最常见的错误:
Module not found:大概率是文件路径写错了,检查 import 语句Type error:TypeScript 类型问题,把报错信息贴给 AI 让它修Hydration mismatch:服务端和客户端渲染不一致,加"use client"指令
万能解法:把错误信息完整复制,粘贴给 AI,说"帮我修这个错误"。 90% 的情况它能直接修好。
第三步:添加完成打勾功能
接下来给每个任务加一个复选框。Prompt:
在任务输入框左边加一个复选框(checkbox),用户可以勾选标记任务已完成。
勾选后任务文字加删除线,颜色变灰。
用另一个 useState 数组管理完成状态。
AI 会更新代码,给每个输入框前加一个 checkbox,并添加完成状态的视觉反馈。
测试一下:输入任务 → 勾选 → 看到删除线效果。到这一步,你的应用已经有了基本的交互。
第四步:连接 Supabase 数据库
数据不能只存在浏览器里(刷新就没了)。我们需要一个数据库。
4.1 创建 Supabase 项目
- 打开 supabase.com,注册账号
- 点击 "New Project",填个名字,选个离你近的区域
- 等 1-2 分钟让数据库初始化
4.2 创建数据表
在 Supabase 控制台的 SQL Editor 里运行:
CREATE TABLE tasks (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
content TEXT NOT NULL,
is_completed BOOLEAN DEFAULT FALSE,
position INTEGER NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
user_id TEXT NOT NULL
);
-- 创建索引加速查询
CREATE INDEX idx_tasks_user_date ON tasks(user_id, created_at);
4.3 安装 Supabase 客户端
npm install @supabase/supabase-js
4.4 配置环境变量
创建 .env.local 文件:
NEXT_PUBLIC_SUPABASE_URL=你的Supabase项目URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=你的Supabase anon key
这两个值在 Supabase 控制台的 Settings → API 里能找到。
4.5 创建 Supabase 客户端
在 src/lib/supabase.ts 中:
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
4.6 修改页面逻辑
Prompt:
修改 page.tsx,实现以下功能:
1. 用 localStorage 生成或获取一个匿名用户 ID(格式:"anon-" + 随机字符串)
2. 页面加载时从 Supabase 读取今天的任务(按 user_id 和 created_at 查询)
3. 点击保存按钮时,将 3 个任务保存到 Supabase(用 upsert,如果今天已有任务就更新)
4. 勾选复选框时,实时更新 Supabase 中的 is_completed 字段
5. 加载中显示 loading 状态
supabase 客户端在 @/lib/supabase 导入。
保存后测试:输入任务 → 保存 → 刷新页面 → 任务还在!
常见问题排查
问题:保存报错 401/403 检查 Supabase 的 Row Level Security (RLS) 设置。开发阶段可以先关闭 RLS:
ALTER TABLE tasks DISABLE ROW LEVEL SECURITY;
问题:查询返回空数组 检查 created_at 的日期过滤逻辑。Supabase 用的是 UTC 时间,和你本地时间可能差一天。Prompt 里让 AI 用当天的起止时间过滤。
问题:数据保存了但刷新后看不到 检查匿名用户 ID 是否每次生成的都一样(应该存在 localStorage 里,不是每次随机生成)。
第五步:添加 AI 鼓励功能
这是最有意思的部分——让 AI 给你加油。
5.1 创建 API 路由
创建 src/app/api/motivate/route.ts:
Prompt:
创建一个 Next.js API Route,路径是 /api/motivate。
功能:
1. 接收 POST 请求,body 包含 tasks 数组(三个任务字符串)
2. 调用 OpenAI API(模型用 gpt-4o-mini,便宜够用)
3. 让 AI 根据用户的三个任务,生成一段简短的鼓励语(100字以内)
4. 同时生成一个实用建议(如何高效完成今天的任务)
5. 返回 JSON:{ message: "鼓励语", tip: "建议" }
用环境变量 OPENAI_API_KEY。
5.2 安装 OpenAI SDK
npm install openai
5.3 设置 OpenAI API Key
在 .env.local 里添加:
OPENAI_API_KEY=sk-你的key
去 platform.openai.com 注册,创建 API Key。新账号通常有免费额度。
5.4 在前端调用
Prompt:
在 page.tsx 的保存按钮下面加一个"✨ 获取今日鼓励"按钮。
点击后:
1. 按钮显示 loading 状态"正在生成..."
2. POST 请求到 /api/motivate,body 是 { tasks: [...] }
3. 收到响应后,在按钮下方显示鼓励语和建议
4. 用卡片样式展示,有橙色主题的 border
5. 如果请求失败,显示友好的错误提示
测试:输入任务 → 点"获取今日鼓励" → 等几秒 → 看到 AI 生成的鼓励语。
如果你看到"正在生成..."卡住了,检查终端有没有报错。最常见的问题是 API Key 没配对,或者 OpenAI 账号没有余额。
第六步:添加统计功能
最后一个核心功能——完成统计。
Prompt:
在页面顶部添加一个统计区域:
1. 今天完成数:X/3
2. 如果 3 个都完成了,显示一个庆祝动画(可以用 emoji 🎉 和简单的 CSS 动画)
3. 显示连续完成天数(连续多少天 3/3 完成)
统计从 Supabase 查询,按用户 ID 过滤。
到这里,你的 MVP 核心功能就全部完成了。
构建-测试-修复循环
以上六个步骤看起来很顺畅,但实际操作中你一定会遇到各种报错。这很正常。
正常的开发流程是这样的:
写代码 → 报错 → 复制错误信息给 AI → AI 修好 → 又报错 → 再给 AI → 运行成功 → 下一个功能
不要因为报错就沮丧。报错是编程的日常,不是你不行的证据。老程序员每天也遇到无数报错,区别只是他们更熟练地搜索答案而已。
几个调试小技巧:
- 一次只改一个东西——如果同时改了三处代码然后报错,你不知道是哪个引起的
- 频繁保存和测试——写完一个小功能就测试,不要写完整个页面才发现有问题
- 善用 console.log——不确定某个变量的值?
console.log(变量名)打印出来看看 - 错误信息是你的朋友——它告诉你哪一行出了什么问题,90% 的情况够你定位问题
本节小结
| 步骤 | 完成了什么 |
|---|---|
| 1. 初始化 | 创建 Next.js + Tailwind 项目 |
| 2. 主页面 | 三个任务输入框 + 保存按钮 |
| 3. 完成打勾 | checkbox + 删除线效果 |
| 4. 数据库 | Supabase 存储任务数据,刷新不丢失 |
| 5. AI 鼓励 | 调用 OpenAI API 生成鼓励语和建议 |
| 6. 统计 | 完成计数 + 连续天数 |
你现在有了一个能用的应用。它可能不好看,但它能跑。
下一节,我们来让它变好看。