Personal climbing log built on Supabase + a single static HTML page. This page is the living picture of how it works, what's left, and what we've intentionally deferred.
One place to see every Colorado peak (plus a few other lists I care about), what I've climbed, and what's left. Cross-device (Mac + iPhone), no native app, no backend of my own to babysit. Data lives in Supabase; the page is plain HTML loaded over HTTPS.
The publishable key is safe to publish — RLS is the actual gate (rows are scoped to my email).
Green dashed = still proposed. Currently I deploy with wrangler pages deploy dist; the end-state replaces that with git-push-to-deploy.
Tier 1 (active): node --test tests/predicates.test.js exercises row-visibility, ranking, and filter-label tables in <1s. Same source runs in both the browser and the test runner.
position_14er_l48 ordinal drives the rank column. AK/HI excluded by design.other_ranked), and immediately selected as a chip in the current log. The Other Peaks stat shows a raw count only (no percentage — the catch-all is, by definition, fully climbed). Orphan cleanup: if an Edit Climb delete would drop the last ascent of an other_ranked-only peak, a confirm prompt warns the peak itself will also be removed from the DB (cascade clears its peak_lists row) — so the Other Peaks list never accumulates uncimbed entries.Things considered and intentionally not built — captured so the reasoning isn't lost.
storageState.json for Supabase auth (gitignored, refreshed when JWT rotates). Asserts page loads, no console errors, PEAKS populates, each filter toggle changes result-count. Add when Tier 1 stops feeling sufficient — likely when Phase 4 edit/delete lands.wrangler pages deploy dist. End-state: push to a git remote, CI does the deploy. Not worth the wiring overhead until I'm pushing more than once a week.climbs table. Today, climb name lives as a denormalized climb_name column on ascents (every row in a day-group carries the same value). A first-class climbs table would let one trip own metadata (name, dates, notes, photos) and many ascent rows reference it — cleaner if a single trip ever spans multiple days, or if I want trip-level fields beyond the name. Not worth the migration yet; revisit if multi-day trips become a common shape.build_prototype.py — HTML template + Python injection (Supabase URL/key, predicates)lib/predicates.js — pure row-visibility / ranking logic (single source of truth)tests/predicates.test.js — Tier 1 unit testsseed.py — idempotent push of canonical data into SupabaseARCHITECTURE.md, CONTEXT.md — long-form project state for future sessions