跳到主要内容

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>
);
}

保存文件,刷新浏览器。你应该能看到一个漂亮的橙色主题页面,有三个输入框和一个按钮。

遇到报错怎么办

如果你看到红色错误信息,先看两个地方:

  1. 终端——看有没有编译错误
  2. 浏览器控制台——按 F12 打开开发者工具

最常见的错误:

  • Module not found:大概率是文件路径写错了,检查 import 语句
  • Type error:TypeScript 类型问题,把报错信息贴给 AI 让它修
  • Hydration mismatch:服务端和客户端渲染不一致,加 "use client" 指令

万能解法:把错误信息完整复制,粘贴给 AI,说"帮我修这个错误"。 90% 的情况它能直接修好。

第三步:添加完成打勾功能

接下来给每个任务加一个复选框。Prompt:

在任务输入框左边加一个复选框(checkbox),用户可以勾选标记任务已完成。
勾选后任务文字加删除线,颜色变灰。
用另一个 useState 数组管理完成状态。

AI 会更新代码,给每个输入框前加一个 checkbox,并添加完成状态的视觉反馈。

测试一下:输入任务 → 勾选 → 看到删除线效果。到这一步,你的应用已经有了基本的交互。

第四步:连接 Supabase 数据库

数据不能只存在浏览器里(刷新就没了)。我们需要一个数据库。

4.1 创建 Supabase 项目

  1. 打开 supabase.com,注册账号
  2. 点击 "New Project",填个名字,选个离你近的区域
  3. 等 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 → 运行成功 → 下一个功能

不要因为报错就沮丧。报错是编程的日常,不是你不行的证据。老程序员每天也遇到无数报错,区别只是他们更熟练地搜索答案而已。

几个调试小技巧:

  1. 一次只改一个东西——如果同时改了三处代码然后报错,你不知道是哪个引起的
  2. 频繁保存和测试——写完一个小功能就测试,不要写完整个页面才发现有问题
  3. 善用 console.log——不确定某个变量的值?console.log(变量名) 打印出来看看
  4. 错误信息是你的朋友——它告诉你哪一行出了什么问题,90% 的情况够你定位问题

本节小结

步骤完成了什么
1. 初始化创建 Next.js + Tailwind 项目
2. 主页面三个任务输入框 + 保存按钮
3. 完成打勾checkbox + 删除线效果
4. 数据库Supabase 存储任务数据,刷新不丢失
5. AI 鼓励调用 OpenAI API 生成鼓励语和建议
6. 统计完成计数 + 连续天数

你现在有了一个能用的应用。它可能不好看,但它能跑。

下一节,我们来让它变好看。