Appearance
Pilates tracker — design
owner: Trunks (researcher) + Squidward (UI)retire_after: 2026-09-23
What
Monitor Pilates classes at Dulwich Leisure Centre via authenticated GladstoneGO scraping. Surface availability + my-bookings in a 30-day interactive calendar in Hinata Studio. Self-decommissions when Michael's membership ends on 2026-09-23.
Architecture
pilates-researcher (Sandpit)
- reads itachi:pilates_key.json
- curl_cffi login + cookie cache
- 30-day timetable scrape
- my-bookings scrape
- JSONL append-only lake (local)
- diff vs previous → Telegram
- POST → /api/pilates/sync
↓
Hinata Studio API + D1
- GET /api/pilates/calendar
- PUT /api/pilates/instance/:id
- POST /api/pilates/sync
- D1 table: pilates_instances
- enabled is user-owned (never overwritten on sync)
↓
PilatesCalendar.tsx
- 30-day grid, rows = class slots, columns = dates
- 4-state palette. Click cell → toggle red ↔ grey.4-state colour rule
StateColourPredicate
cancelledred stripedstatus === 'cancelled'bookedgreenbooked === truedisabledred 55% opacityenabled === false OR (date < today AND not booked) availableyellowspaces > 0 AND enabled AND not booked monitoringgreydefault — enabled, polling, no spaces yet
Telegram policy
Per feedback_telegram_only_on_breakage — pings ONLY:
0 spots → N spotstransition on an enabled, unbooked slot (book now)3 consecutive non-zero exits from
run-scheduled.sh(real breakage)Retirement boot (one-time goodbye on 2026-09-24+)
Retirement (2026-09-23)
On 2026-09-24+: run.py writes .retired sentinel, fires one Telegram goodbye. run-scheduled.sh short-circuits all subsequent fires. PilatesCalendar.tsx checks isPilatesActive() → renders a retirement card instead of the grid.
◆ hinata · projects/hinata-architecture/pilates-tracker.html · phase-19 conversion