A daily Philadelphia Phillies content site: a static newsletter, a set of dashboard surfaces, a lightweight JSON pipeline, and a GitHub Pages deployment target. Zero backend — every data source is a public API.
Built: March 28, 2026
Version: 1.6.1
Stack: Vanilla HTML, CSS custom properties, Node ESM scripts, GitHub Pages
Canonical docs: CLAUDE.md (source of truth) · HANDOFF.md (orientation) · docs/SPEC.md (site spec)
| Surface | URL |
|---|---|
| Newsletter | https://davehomeassist.github.io/phillies-wire/ |
| Dashboard | https://davehomeassist.github.io/phillies-wire/dashboard/ |
| Innings timeline | https://davehomeassist.github.io/phillies-wire/dashboard/innings/ |
| Preferences | https://davehomeassist.github.io/phillies-wire/dashboard/preferences/ |
| Accuracy scorecard | https://davehomeassist.github.io/phillies-wire/dashboard/accuracy/ |
| Schedule tracker | https://davehomeassist.github.io/phillies-wire/schedule/ |
phillies-wire/
|-- tokens.css, phillies-wire.css # design tokens + styles
|-- crawl.mjs, enrich.mjs, render.mjs # pipeline stages
|-- verify.mjs, deliver.mjs, run.mjs # gate, optional email, orchestrator
|-- factcheck.mjs # pre-publish gate + daily fact-check + accuracy export
|-- config.mjs # centralized constants
|-- live-feed.js # browser-side live polling
|-- data/phillies-2026.json # canonical season schedule (source of truth)
|-- calendar/phillies-2026-all.ics # season ICS
|-- embed/ticker.html # iframe-safe ticker
|-- dashboard/ # dashboard, innings, preferences, accuracy
|-- schedule/ # merged schedule tracker
|-- issues/, archive/, archive.json # generated newsletter output
|-- scripts/ # lint.mjs, test-runner.mjs, health-check.mjs
|-- test/, test/reliability/ # unit + reliability suites
|-- .github/workflows/publish.yml # CI publish + deploy
`-- README.md, HANDOFF.md, CLAUDE.md, docs/
run.mjs -> crawl.mjs -> edition sync -> enrich.mjs -> render.mjs -> verify.mjs -> deliver.mjs? -> factcheck.mjs
-> latest index + dated issue + per-issue data.json + archive.json + archive/index.html
-> latest.json feed + canonical schedule JSON + ICS calendar + ticker + accuracy scorecard
Run locally (pull first — main advances on every cron run):
git pull
node run.mjsOr stage-by-stage:
node crawl.mjs
ANTHROPIC_API_KEY=sk-... node enrich.mjs
node render.mjs
node verify.mjsverify.mjs is a hard pre-publish gate. It runs the deterministic fact-check (runFactcheck) and asserts the per-issue data.json contract, canonical schedule JSON, season calendar copy, latest.json schema + freshness, ticker render functions + iframe safety, the accuracy scorecard contract, plus SEO/accessibility tags and a mojibake/injection scan. Any failure breaks the publish on purpose.
crawl.mjsstill publishes when the MLB injuries endpoint 404s by deriving IL from the season transactions feed plus the fixture baseline.crawl.mjssupports same-day payload overrides for editorial corrections.enrich.mjssends an editorial-only payload to Claude; ifANTHROPIC_API_KEYis missing or enrich fails, the site publishes a structured fallback instead of failing the issue.run.mjsreuses the current day's edition number on reruns and increments only when a new publication date is crawled.
factcheck.mjs runs in two modes (see docs/FACTCHECK.md):
- Pre-publish (deterministic, offline) — invoked by
verify.mjs; blocks publish on render bugs or factual contradictions. - Daily (source-verified vs MLB Stats API) — run by
run.mjspost-publish via--export-accuracy, which powers the/dashboard/accuracy/scorecard and upserts a Notion report.
- Workflow:
.github/workflows/publish.yml - Triggers:
workflow_dispatch, daily cron, and game-window refresh cron - Output: GitHub Pages deploy, then a committed archive snapshot on
main(deploy runs before the persist commit to avoid a push race) - Diagnostics: each run uploads rendered HTML, archive manifest/page, data JSON,
status.json, and any stage error logs
statsapi.mlb.com— schedule, boxscore, injuries,feed/liveplay-by-playopen-meteo.com— weather- MLB transactions feed — injury/rehab freshness (and IL fallback when
/injuries404s)
Versioned by schema_version string; breaking changes bump the major:
- Per-issue
data.json—1.3.0 latest.jsonfeed —latest-1.0.0- Canonical schedule
data/phillies-2026.json—1.0.0 - Accuracy scorecard —
accuracy-1.0.0
- Critical-CSS inlining for faster first paint (fonts are already self-hosted).
- Bullpen availability card driven by rolling reliever usage.
- Stable alternate source for the team injuries endpoint (issue 004).
- Playwright end-to-end smoke test for the live-feed pipeline.
- LLM Conversation Log: https://www.notion.so/331255fc8f44814483d4d11fd2703f68
- Pipeline Spec page: https://www.notion.so/331255fc8f44818ea2baf23a71c91645
- Code Dashboard LIVE: https://www.notion.so/331255fc8f44819d9d88c8ef21105082