CodingIdeas.ai
← Browse All Ideas

Build Guide

How to Build a Pomodoro Timer

A Pomodoro timer with session analytics and AI focus coaching outperforms every $10/month productivity app — and you can build it in a day.

Beginner1 day

Pomodoro timers cover interval logic, browser notifications, sound effects, and local persistence — plus it's immediately useful for your own workflow.

Data model

The core tables you'll need before writing any UI.

Sessionid, user_id, task_label, duration_minutes, type (work/short_break/long_break), completed (bool), started_at, ended_at
Settingsuser_id, work_duration (default 25), short_break (default 5), long_break (default 15), sessions_before_long_break (default 4), sound_enabled, notification_enabled

Build order

The sequence that minimises rewrites — build in this order.

1

Countdown timer core

Store the end time as a timestamp (Date.now() + duration × 60000) when the timer starts. On each tick (useInterval at 1s), calculate remaining = endTime - Date.now(). This works correctly even if the tab is backgrounded.

2

Work / break cycle

Track session count in state. After each work session, auto-start a short break. After every 4 work sessions, auto-start a long break. Show which phase you're in (Work / Short Break / Long Break).

3

Sound and notifications

Play a short audio file (new Audio(url).play()) when the timer ends. Request notification permission on first use. Show a browser notification on session end with the Notifications API.

4

Task label

Add an input above the timer: "What are you working on?" Store the label with each completed session so the history is meaningful.

5

Session history

Save each completed session to localStorage (or Supabase). Show a history list: task, duration, when. Calculate today's total focus time and display it as a KPI.

6

Settings panel

Add a settings drawer to customise work/break durations and the number of sessions before a long break. Persist to localStorage. Apply immediately to the next session.

7

AI weekly focus report

On Monday, aggregate last week's sessions: total focus hours, most productive day, most common task labels. Send to Claude Haiku and get back a 3-sentence coaching comment.

Done when

Observable behaviors that confirm V1 is complete — verify each one before you ship.

  • Timer countdown is accurate after switching tabs for 5 minutes and returning

  • Browser notification fires at session end when permission has been granted

  • Session history persists after a browser refresh — data is not lost on reload

  • Today's total focus time KPI card updates in real time as sessions complete

  • App launches immediately with default settings (25/5/15) — zero configuration needed

First Run Requirement

App opens with default work/break settings pre-populated and one Getting Started session in history so the UI is never blank. No setup required.

Build it with AI — Architect Prompt

Paste this into Claude, Cursor, Windsurf, or any AI coding tool. It includes the full context of this guide — data model, build order, done conditions, and pitfalls — so the AI starts with everything it needs.

ClaudeCursorWindsurfCopilotGemini
architect-prompt.txt
<context>
App: Pomodoro Timer
Difficulty: Beginner
Estimated build time: 1 day
Tech stack (intermediate): Next.js + Supabase for session history + Clerk for cross-device sync

Data model:
  Session: id, user_id, task_label, duration_minutes, type (work/short_break/long_break), completed (bool), started_at, ended_at
  Settings: user_id, work_duration (default 25), short_break (default 5), long_break (default 15), sessions_before_long_break (default 4), sound_enabled, notification_enabled

FIRST RUN REQUIREMENT:
App opens with default work/break settings pre-populated and one Getting Started session in history so the UI is never blank. No setup required.

DONE WHEN — verify each before marking V1 complete:
  □ Timer countdown is accurate after switching tabs for 5 minutes and returning
  □ Browser notification fires at session end when permission has been granted
  □ Session history persists after a browser refresh — data is not lost on reload
  □ Today's total focus time KPI card updates in real time as sessions complete
  □ App launches immediately with default settings (25/5/15) — zero configuration needed

Recommended build order:
  1. Define API contract + schema + seed data (always first)
  2. Countdown timer core — Store the end time as a timestamp (Date.now() + duration × 60000) when the timer starts. On each tick (useInterval at 1s), calculate remaining = endTime - Date.now(). This works correctly even if the tab is backgrounded.
  3. Work / break cycle — Track session count in state. After each work session, auto-start a short break. After every 4 work sessions, auto-start a long break. Show which phase you're in (Work / Short Break / Long Break).
  4. Sound and notifications — Play a short audio file (new Audio(url).play()) when the timer ends. Request notification permission on first use. Show a browser notification on session end with the Notifications API.
  5. Task label — Add an input above the timer: "What are you working on?" Store the label with each completed session so the history is meaningful.
  6. Session history — Save each completed session to localStorage (or Supabase). Show a history list: task, duration, when. Calculate today's total focus time and display it as a KPI.
  7. Settings panel — Add a settings drawer to customise work/break durations and the number of sessions before a long break. Persist to localStorage. Apply immediately to the next session.
  8. AI weekly focus report — On Monday, aggregate last week's sessions: total focus hours, most productive day, most common task labels. Send to Claude Haiku and get back a 3-sentence coaching comment.
  9. End-to-end verification — walk every Done When condition above (always last)

Known pitfalls to avoid:
  - Using setInterval for the countdown — intervals drift and pause in background tabs. Store the target end timestamp and compute remaining time as endTime - Date.now() on each render.
  - Auto-starting breaks without user confirmation — some users want to take control between sessions. Add a setting for "auto-start breaks" and default it to off.
  - Not preserving timer state on refresh — if the user refreshes the page, their 20-minute work session is gone. Store startTime and duration in sessionStorage so it survives a refresh.
</context>

<role>
You are a Senior Full-Stack Engineer and product architect who has shipped production Pomodoro Timers before. You know exactly where developers get stuck and how to structure the project to avoid rewrites.
</role>

<task id="step-1-clarify">
Before writing any code or spec, ask me 3–5 clarifying questions that will meaningfully change the architecture. Focus on: scale expectations, auth requirements, platform (web / mobile / both), must-have vs nice-to-have features for the MVP, and any hard constraints (budget, deadline, existing infrastructure).

<example>
BAD: "What tech stack do you want to use?" — too broad, doesn't change architecture decisions.
GOOD: "Do you need real-time sync across devices, or is single-device with periodic refresh acceptable? This decides whether we use WebSockets or simple REST polling and significantly affects infrastructure complexity."
</example>

⚠️ Do NOT start planning or writing code until I answer. Present the questions, then stop and wait.
</task>

<task id="step-2-architect">
After I answer your questions, produce the following in order:

1. TECHNICAL SPECIFICATION
   - System architecture using → to show data and event flow
   - Core data model (refer to data model in <context>)
   - API contract — list ALL routes with request/response shapes BEFORE any implementation
     WHY: agreeing on contracts first prevents rewrites when frontend and backend shapes diverge
   - External APIs and integration points

2. MVP PLAN in three phases:

   SETUP   ✦ Step 1 (always): API contract + schema migration + seed data
     Done when: schema is migrated, seed script runs, app starts with demo data, zero manual setup.

   CORE FEATURES — build in this exact order:
   2. Countdown timer core
   3. Work / break cycle
   4. Sound and notifications
   5. Task label
   6. Session history
   7. Settings panel
   8. AI weekly focus report

   DONE WHEN — one observable condition per feature:
   □ Timer countdown is accurate after switching tabs for 5 minutes and returning
   □ Browser notification fires at session end when permission has been granted
   □ Session history persists after a browser refresh — data is not lost on reload
   □ Today's total focus time KPI card updates in real time as sessions complete
   □ App launches immediately with default settings (25/5/15) — zero configuration needed

   STRETCH GOALS — post-launch additions that are explicitly out of V1 scope.

3. BLOCKER ANALYSIS
   Flag: API rate limits, auth complexity, scope risks, cold-start problems, top 2–3 failure modes.

   FIRST RUN REQUIREMENT: App opens with default work/break settings pre-populated and one Getting Started session in history so the UI is never blank. No setup required.
   ✓ Done when: app launches with seed data and the full user journey works without any manual setup.

<self_check>
Before presenting your output, verify:
□ Every answer I gave to clarifying questions is reflected in the spec
□ Step 1 is ALWAYS: API contract + schema + seed — never UI first
□ Done When criteria are observable user behaviors, not internal states
□ The plan is realistic for one person to ship within 1 day
□ All known pitfalls from <context> are addressed in the spec
</self_check>
</task>

<task id="step-2.5-agents-md">
Generate an AGENTS.md file at the project root. This file is read automatically by Claude Code, Cursor, Windsurf, and all major AI coding tools at the start of every session.

Include:
- Project overview (2–3 sentences)
- Tech stack with exact version numbers
- Folder structure with one-line descriptions per directory
- Key architectural decisions and the WHY behind each
- Coding conventions: camelCase components, kebab-case files, max 200 lines per file, one concern per file
- Available commands: dev, build, test, lint, db:migrate, db:seed
- MVP scope boundaries — features explicitly out of V1

Note in the file: "Cursor users: symlink .cursorrules → AGENTS.md. Claude Code users: symlink CLAUDE.md → AGENTS.md."
</task>

<task id="step-3-implement">
Implement the full project in the exact order from step 2. For each step:
- Write complete code (no placeholders or TODOs)
- Confirm the step works before moving to the next

<constraints>
- Step 1 is ALWAYS: define all API routes + TypeScript request/response interfaces + run schema migration
  WHY: agreeing on contracts before writing a single component prevents shape mismatches that require rewrites
- Final step is ALWAYS: start the app and walk every Done When condition from <context> end-to-end
  WHY: a spec that passes unit tests but breaks the core user journey is not done
- Max 200 lines per file. WHY: every file must fit in one AI context window for complete reasoning
- One concern per file. WHY: mixing auth logic into API routes makes it impossible to reuse — extract to lib/auth.ts
- TypeScript strict mode, no `any` types. WHY: catches data shape mismatches at compile time, not in production
- All database queries in server components or API routes only. WHY: keeps credentials server-side
- All environment variables documented in .env.example. WHY: next developer sets up in under 5 minutes
</constraints>
</task>

How to use this prompt

  1. 1.Copy the prompt above
  2. 2.Open Claude, Cursor (Cmd+L), or Windsurf
  3. 3.Paste the prompt and send — the AI will ask 3–5 clarifying questions
  4. 4.Answer the questions, then it generates your full project spec
  5. 5.Continue in the same session to implement step by step

Common mistakes

What trips up most developers building this for the first time.

⚠️

Using setInterval for the countdown — intervals drift and pause in background tabs. Store the target end timestamp and compute remaining time as endTime - Date.now() on each render.

⚠️

Auto-starting breaks without user confirmation — some users want to take control between sessions. Add a setting for "auto-start breaks" and default it to off.

⚠️

Not preserving timer state on refresh — if the user refreshes the page, their 20-minute work session is gone. Store startTime and duration in sessionStorage so it survives a refresh.

Recommended tech stack

Pick the level that matches your experience.

Beginner

Vanilla JS or React + localStorage — complete in a few hours

Intermediate

Next.js + Supabase for session history + Clerk for cross-device sync

Advanced

Next.js + Supabase + Claude API for focus coaching + Tauri for a native desktop app

Take it further — related ideas

Each comes with revenue math, a full build guide, and a prompt to paste into Claude or Cursor.