Week 1 · 01-habit-tracker

Habit tracker with auth and CRUD

Email/password auth, per-user habits (create, rename, delete), daily check-in with streak counter, strict per-user data isolation.

max follow-ups: 3 timebox: 60 min

Rules

Prompt (paste verbatim)

# BuildOff Spec #1 — "Streaky" habit tracker

> Paste everything between the two horizontal rules below, verbatim, as the **first and only initial prompt**. Do not add anything else.

---

Build a production-ready web app called **Streaky**: a personal daily habit tracker.

## Requirements

1. **Landing page** at `/` with the app name "Streaky", a one-sentence description, and two links: "Sign up" and "Log in".
2. **Sign up** with email + password (minimum 8 characters). After a successful sign-up the user is logged in and taken straight to the dashboard.
3. **Email confirmation must be disabled** — a newly created account must be usable immediately. Any syntactically valid email address must be accepted.
4. **Log in / log out.** Wrong credentials show a visible error message. Logging out returns to the landing page or the log-in page.
5. **Dashboard** (the page shown after login) is only accessible to logged-in users. Visiting it while logged out must redirect to the log-in page or show the log-in form — never another user's data.
6. **Create habit**: a text input and an "Add" button. Habit names are 1–60 characters; an empty (or whitespace-only) name must be rejected without creating a habit.
7. **List habits** belonging to the logged-in user only, newest first. When there are none, show an empty-state message.
8. **Rename habit** inline (edit button → text input → save).
9. **Delete habit** with a single click on a delete button (a confirmation dialog is allowed only if it is a native `confirm()`).
10. **Daily check-in**: each habit has a toggle to mark it done for today (in the user's local time zone). Toggling again un-marks it.
11. **Streak**: each habit shows its current streak — the number of consecutive days, ending today, on which it was marked done. A habit marked done today for the first time shows a streak of **1**; un-marking it today shows **0**.
12. **Persistence**: all data is stored in a real backend database and survives page reloads, logging out and logging back in, and using a different browser.
13. **Security**: users must never be able to read or modify another user's habits or check-ins, including via direct API/database calls. Never expose secret/service keys in client code. Enable row-level security (or the equivalent) on every table.
14. **Responsive**: fully usable at 375 px wide without horizontal scrolling.
15. **Publish** the app to a public URL.

## Testability contract (mandatory)

Add these exact `data-testid` attributes. Automated tests depend on them.

| Element | data-testid |
|---|---|
| Sign-up email input / password input / submit button | `signup-email` / `signup-password` / `signup-submit` |
| Log-in email input / password input / submit button | `login-email` / `login-password` / `login-submit` |
| Visible authentication error message | `auth-error` |
| Log-out button (visible on the dashboard) | `logout-button` |
| New-habit name input / add button | `habit-name-input` / `habit-add-button` |
| Empty-state message (no habits) | `empty-state` |
| Each habit row (container) | `habit-item` |
| Habit name text inside a row | `habit-name` |
| Done-today toggle inside a row (checkbox or button; expose state via `aria-pressed` or `checked`) | `habit-checkin-toggle` |
| Streak number inside a row (the element's text contains just the number) | `habit-streak` |
| Rename button / rename input / save button inside a row | `habit-edit-button` / `habit-edit-input` / `habit-save-button` |
| Delete button inside a row | `habit-delete-button` |

The "Sign up" and "Log in" links on the landing page must be real links (`<a>`) whose visible text is exactly "Sign up" and "Log in".

---

Test suite

Playwright tests live at specs/01-habit-tracker/tests.spec.ts. See the methodology for how pass rate becomes a score.