Overview
- What: a task manager for people juggling several projects, with priorities, due dates, tags, a calendar and a dashboard.
- Hardest problem: keeping it server-authoritative: every button performs a real database operation and every dashboard number is derived from a query.
- How it is validated: 147 Vitest tests, each on a real in-memory PostgreSQL with real migrations, plus 39 Playwright tests against a production build.
It runs on embedded PostgreSQL (PGlite) with no setup, or any PostgreSQL 13+ in production. Demo accounts are listed in the README.
Architecture
browser --> Next.js 16 (App Router, RSC, server actions)
| session cookie (httpOnly, HMAC-hashed token)
v
Drizzle ORM: every query scoped by WHERE user_id = ?
|
PostgreSQL (PGlite locally / any PostgreSQL 13+ in production)
filters, sort, search, pagination: URL state --> SQL Highlights
- Authorisation lives in the
WHEREclause (eq(tasks.userId, userId)on every query), so another user's row and a missing row are both a 404;tests/authorization.test.tsasserts cross-user isolation from the outside. - Custom session auth: scrypt (N=16384) password hashes, 256-bit tokens stored only as HMACs, httpOnly SameSite=Lax cookies, timing-matched failed logins, fixed-window rate limits.
- Filter, sort, search and pagination state live in the URL and execute as SQL (stable tiebreak, LIKE-wildcard escaping, 300 ms debounce); time-zone-correct "overdue / due today" across DST and half-hour offsets.
- Hand-built accessible UI primitives (~900 lines: dialog focus trap, arrow-key menus, live-region toasts) and server-rendered inline SVG charts.
- 147 Vitest tests across 8 files, each booting a real in-memory PostgreSQL and running real migrations; 39 Playwright tests (desktop, mobile, auth flows) against a production build.
- Seven tables, eight composite indexes led by
user_id; Zod 4 schemas shared by client and server.
What I learned
Putting authorization in the WHERE clause, so a foreign row and a missing row are both a 404, removed a whole class of leaks and made the cross-user test simple to write. Testing against a real in-memory PostgreSQL with real migrations caught things mocks would have hidden.