7.2 Build the MVP: From Zero to Working
In the last section we wrote the PRD. Now it's time to actually write code.
Don't worry. You don't need to hand-write every line from scratch. Our strategy: use AI as your pair programming partner — you steer, AI builds.
Step 1: Initialize the Project
Open your terminal and run:
npx create-next-app@latest daily-focus --typescript --tailwind --eslint --app --src-dir --import-alias "@/*"
This command will ask a few questions — just press Enter through all of them. It creates a Next.js project with TypeScript and Tailwind CSS pre-configured.
Once created, enter the project directory:
cd daily-focus
npm run dev
Open your browser and visit http://localhost:3000. You'll see the default Next.js page.
Congratulations, your project is running. It doesn't have any features yet, but it's running — and that's the most important step.
Step 2: Create the Main Page
Now open your AI coding tool (Claude Code or Cursor) and enter your first prompt:
I'm building a web app called "AI Daily Focus Helper."
Please modify src/app/page.tsx to create the main page with these requirements:
1. Page title: "🎯 AI Daily Focus Helper"
2. Subtitle: "Focus on the 3 most important things every day"
3. Three input fields with placeholders "Most important thing today #1" "#2" "#3"
4. A save button
5. Tailwind CSS styling, clean modern design, centered layout
Use React useState to manage input state.
The AI will generate something like this:
"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 Daily Focus Helper
</h1>
<p className="text-center text-gray-500 mt-2 mb-8">
Focus on the 3 most important things every day
</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={`Most important thing today #${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">
Save Today's Focus
</button>
</div>
</main>
);
}
Save the file and refresh the browser. You should see a beautiful orange-themed page with three input fields and a button.
What to Do When You Hit an Error
If you see red error messages, check two places first:
- Terminal — look for compilation errors
- Browser console — press F12 to open DevTools
Most common errors:
Module not found: Probably a wrong file path — check your import statementsType error: TypeScript type issue — paste the error message to AI and ask it to fix itHydration mismatch: Server and client rendering mismatch — add the"use client"directive
Universal fix: copy the full error message, paste it to AI, and say "fix this error." It works 90% of the time.
Step 3: Add Checkbox Completion
Next, add a checkbox to each task. Prompt:
Add a checkbox to the left of each task input. Users can check it to mark a task as completed.
When checked, the task text gets a strikethrough and turns gray.
Use another useState array to manage completion state.
The AI will update the code, adding a checkbox before each input field with visual feedback for the completed state.
Test it: enter tasks → check them off → see the strikethrough effect. At this point, your app has basic interactivity.
Step 4: Connect to Supabase Database
Data can't only live in the browser (it disappears on refresh). We need a database.
4.1 Create a Supabase Project
- Go to supabase.com and sign up
- Click "New Project," give it a name, pick a region close to you
- Wait 1-2 minutes for the database to initialize
4.2 Create the Data Table
Run this in the Supabase console's 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 to speed up queries
CREATE INDEX idx_tasks_user_date ON tasks(user_id, created_at);
4.3 Install the Supabase Client
npm install @supabase/supabase-js
4.4 Configure Environment Variables
Create a .env.local file:
NEXT_PUBLIC_SUPABASE_URL=your-supabase-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key
You can find these values in the Supabase console under Settings → API.
4.5 Create the Supabase Client
In 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 Update the Page Logic
Prompt:
Modify page.tsx to implement the following:
1. Use localStorage to generate or retrieve an anonymous user ID (format: "anon-" + random string)
2. On page load, read today's tasks from Supabase (query by user_id and created_at)
3. When the save button is clicked, save the 3 tasks to Supabase (use upsert — update if today's tasks already exist)
4. When a checkbox is toggled, update the is_completed field in Supabase in real-time
5. Show a loading state while data is loading
Import the supabase client from @/lib/supabase.
Test after saving: enter tasks → save → refresh the page → tasks are still there!
Troubleshooting Common Issues
Problem: Save returns 401/403 error Check Supabase's Row Level Security (RLS) settings. For development, you can disable RLS:
ALTER TABLE tasks DISABLE ROW LEVEL SECURITY;
Problem: Query returns an empty array Check the date filtering logic for created_at. Supabase uses UTC time, which may differ from your local time by a day. Have AI filter by the day's start and end times in the prompt.
Problem: Data saves but doesn't appear after refresh Check that the anonymous user ID is consistent across requests (it should be stored in localStorage, not randomly generated each time).
Step 5: Add the AI Encouragement Feature
This is the fun part — letting AI cheer you on.
5.1 Create the API Route
Create src/app/api/motivate/route.ts:
Prompt:
Create a Next.js API Route at /api/motivate.
Functionality:
1. Accept POST requests with a body containing a tasks array (three task strings)
2. Call the OpenAI API (model: gpt-4o-mini — affordable and sufficient)
3. Have AI generate a short encouragement message (under 100 words) based on the user's three tasks
4. Also generate a practical tip (how to efficiently complete today's tasks)
5. Return JSON: { message: "encouragement", tip: "tip" }
Use the OPENAI_API_KEY environment variable.
5.2 Install the OpenAI SDK
npm install openai
5.3 Set Up the OpenAI API Key
Add to .env.local:
OPENAI_API_KEY=sk-your-key
Go to platform.openai.com to sign up and create an API Key. New accounts usually have free credits.
5.4 Call from the Frontend
Prompt:
Below the save button in page.tsx, add a "✨ Get Today's Encouragement" button.
When clicked:
1. Button shows a loading state: "Generating..."
2. POST request to /api/motivate with body { tasks: [...] }
3. After receiving the response, display the encouragement and tip below the button
4. Display in a card style with an orange-themed border
5. If the request fails, show a friendly error message
Test: enter tasks → click "Get Today's Encouragement" → wait a few seconds → see the AI-generated encouragement.
If "Generating..." gets stuck, check the terminal for errors. The most common issues are a misconfigured API Key or an OpenAI account with no balance.
Step 6: Add Statistics
The last core feature — completion stats.
Prompt:
Add a stats area at the top of the page:
1. Today's completion count: X/3
2. If all 3 are complete, show a celebration animation (use emoji 🎉 and simple CSS animation)
3. Show consecutive completion days (how many days in a row all 3/3 were completed)
Stats are queried from Supabase, filtered by user ID.
At this point, all the core features of your MVP are complete.
The Build-Test-Fix Cycle
The six steps above look smooth, but in practice you'll hit all kinds of errors. That's completely normal.
The real development flow looks like this:
Write code → Error → Copy error to AI → AI fixes it → Another error → Back to AI → It works → Next feature
Don't get discouraged by errors. Errors are a daily part of programming — not evidence that you're not cut out for this. Senior developers hit countless errors every day too; the difference is they're more practiced at searching for answers.
A few debugging tips:
- Change one thing at a time — if you change three things and get an error, you won't know which one caused it
- Save and test frequently — test after each small feature, don't wait until the whole page is done
- Use console.log — not sure what a variable's value is?
console.log(variable)and take a look - Error messages are your friends — they tell you which line has what problem, and 90% of the time that's enough to locate the issue
Chapter Summary
| Step | What Was Accomplished |
|---|---|
| 1. Initialize | Created Next.js + Tailwind project |
| 2. Main page | Three task inputs + save button |
| 3. Checkbox completion | Checkboxes + strikethrough effect |
| 4. Database | Supabase stores task data, persists across refreshes |
| 5. AI encouragement | Calls OpenAI API for encouragement and tips |
| 6. Statistics | Completion count + streak days |
You now have a working application. It might not look pretty, but it works.
In the next section, we'll make it look good.