▍ humdrum codex / soft
6.3 KB raw

Design — Working terminal refresh + past/upcoming scores

Date: 2026-07-08 Status: approved (pending spec review)

Context

The first-class surfaces of this project are the terminal TUI (tui/dashboard.py, Textual/Python, launched via the dashboard command → uv run) and the morning paper (morning-paper script → POST /api/edition → puppeteer renders /print to a PDF). The Next.js webapp at :4317 is effectively the backend: it serves /api/* (data) and /print (paper source). The interactive webapp UI is not a priority.

Two problems motivate this work:

  1. TUI refresh doesn't work. fetch_sources() calls bare GET /api/sources, which returns cached snapshots only (currentState). The server supports ?fresh=1 (refresh stale sources) and ?force=1 (refresh all), but the TUI never sends them — so pressing r just re-reads the same cache. Root cause: missing query param.

  2. No previous-day scores, and no live updates. lib/sources/modules/sports.ts fetches only today → +daysAhead (never yesterday). lib/edition-data.ts:70 already wants yesterday..today for the paper but the data was never fetched. The sports source also refreshes every 600s, so live scores never move in the TUI within a game.

Data source finding

The user's separate sportsball TUI (~/Developer/Home/sportsball, Go/Bubble Tea) keeps live scores fresh. Investigation: it pulls the same ESPN public API the dashboard already uses — https://site.api.espn.com/apis/site/v2/sports/{sport}/{league}/scoreboard (internal/espn/client.go:19). There is no better data to sync to, and sportsball has no API or persisted score store (config.json holds only favorites) — nothing to sync from. So we borrow its techniques, staying independent:

Decisions

Changes

1. TUI refresh (tui/dashboard.py)

2. Sports module + schema (lib/sources/modules/sports.ts, lib/schemas/sources/sports.ts)

3. Favorites sync on TUI open (tui/dashboard.py)

4. Shared bucketing — FINAL / TODAY / UPCOMING

5. TUI render_sports + live poll (tui/dashboard.py)

6. Paper (app/print/page.tsx)

Out of scope

Verification