About this build
A real tool I use daily, engineered as a portfolio piece.
Why I built it
I walk on a treadmill at the gym and outdoors. That data used to live in two disconnected places — my head (speed/incline/duration) and Apple Health (passive steps, distance, outdoor walks) — so I had no long-term view of total movement and no record to look back on a year from now.
Olympic reconciles both sources into one dashboard: daily, weekly, monthly, and a year-long heatmap. It stays a ten-second logging tool on my phone while doubling as something a hiring manager can open in two minutes with no login.
How the data flows
Apple Health arrives two ways — a one-time backfill zip and a nightly push from the Health Auto Export app — and both land in Postgres as phone-reported daily metrics plus outdoor walks. Treadmill sessions are logged directly. Because the phone already counts treadmill steps, displayed totals subtract each treadmill workout's own steps/distance/calories from the phone total for that day, then add the treadmill figures back — so a workout is counted once, computed fresh on every read.
Decisions & tradeoffs
Read-time dedup over precomputed totals
Phone and treadmill both count the same steps. Rather than maintaining a reconciled total on every write, the overlap is subtracted at read time — one rule, no drift, and re-importing Apple Health is always safe.
Passkeys over passwords
One human, several devices, no password to phish or leak. A signed httpOnly cookie carries the session; credentials live in Postgres. Registration is gated by a one-time bootstrap secret so a public /register can't be abused.
Route-level access control over deployment protection
v1 hid everything behind Vercel SSO. v2 needs a public dashboard and a private write side from one deployment, so a single requireOwner() guard wraps every mutation and secret-bearing route, and public reads go through field-whitelist DTOs.
Single-user, no multi-tenancy
No user_id columns, no sign-up, no org model. The public audience is anonymous and read-only; the owner is me. That keeps the schema and the surface area small.
PWA over native
The daily job is logging a workout one-handed at the gym. A home-screen PWA with an offline save queue does that without an app store, and installs for any public visitor too.
Stack & live metrics
Figures above are queried live at render (tests captured at build). Lighthouse on production: Accessibility 100, Best Practices 100, SEO 100.
- Framework
- Next.js 16 App Router (TypeScript)
- UI
- shadcn/ui + Tailwind CSS
- Charts
- Recharts + react-activity-calendar
- Database
- Neon Postgres (Vercel Marketplace)
- ORM
- Drizzle
- Auth
- WebAuthn passkeys + jose-signed session cookie
- Hosting
- Vercel (Fluid Compute, Node.js)