{"id":51633573,"url":"https://github.com/quarterback/vroomtv","last_synced_at":"2026-07-13T11:02:15.909Z","repository":{"id":364182736,"uuid":"1266733829","full_name":"quarterback/vroomtv","owner":"quarterback","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-12T02:07:28.000Z","size":27,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T02:13:33.374Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quarterback.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-11T22:49:23.000Z","updated_at":"2026-06-12T01:06:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/quarterback/vroomtv","commit_stats":null,"previous_names":["quarterback/vroomtv"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/quarterback/vroomtv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarterback%2Fvroomtv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarterback%2Fvroomtv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarterback%2Fvroomtv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarterback%2Fvroomtv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quarterback","download_url":"https://codeload.github.com/quarterback/vroomtv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarterback%2Fvroomtv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35420322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-13T02:00:06.543Z","response_time":119,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-13T11:02:14.950Z","updated_at":"2026-07-13T11:02:15.903Z","avatar_url":"https://github.com/quarterback.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vroomtv — Rocky Mountain News (Sports)\n\nA cross-sport sports section in a modern newspaper design (The Athletic ×\nSporting News, with an ESPN-style scoreboard strip). It aggregates live\nresults from three sports sims into one front page: scores, standings,\nstat leaders, news stories, and game detail pages — server-rendered HTML\nwith a few lines of JS for the scoreboard's league filter.\n\n| Sport | Sim | Live site |\n| --- | --- | --- |\n| ⚾ Baseball (O27 variant) | [quarterback/hybrid-baseball](https://github.com/quarterback/hybrid-baseball) | [superinnin.gs](https://superinnin.gs) |\n| 🏉 Viperball | [quarterback/viperball](https://github.com/quarterback/viperball) | [viperball.xyz](https://viperball.xyz) |\n| 🎾 Tennis (GTT + NCAA) | [quarterback/tennis-team-manager](https://github.com/quarterback/tennis-team-manager) | [pctennis.xyz](https://pctennis.xyz) |\n\n## How it works\n\nThe hub never talks to the sims' servers and never imports their code. It\nopens each sim's SQLite database **read-only** (`?mode=ro`) and renders\nstraight from there:\n\n- One adapter per sport (`adapters/baseball.py`, `adapters/viperball.py`,\n  `adapters/tennis.py`). Each knows its sim's schema and returns plain\n  dicts; the Flask layer (`app.py`) never touches SQL.\n- **Graceful degradation** — any sport whose DB is unconfigured or missing\n  shows a wire-service placeholder instead of an error. The hub runs fine\n  with zero, one, two, or three databases.\n- **Multi-league throughout** — viperball renders every `pro_league` save\n  in the DB, tennis renders every GTT league and every NCAA season. New\n  leagues appear with zero code changes.\n\n## Running\n\n```bash\npip install -r requirements.txt\n\nBASEBALL_DB=/path/to/hybrid-baseball/o27v2/o27v2.db \\\nVIPERBALL_DB=/path/to/viperball/data/viperball.db \\\nTENNIS_DB=/path/to/tennis-team-manager/tennis.db \\\npython manage.py runserver\n```\n\nServes on port **5050** (`PORT` to override). All three env vars are\noptional.\n\n\u003e Baseball note: if the sim uses its saves registry, the live DB is\n\u003e `o27v2/saves/\u003csave-hash\u003e.db` rather than `o27v2/o27v2.db` — point\n\u003e `BASEBALL_DB` at the actual file.\n\n## Deploying\n\nThe repo ships a `Dockerfile` and `fly.toml` (mirroring the three sims,\nwhich all run on Fly). From the repo root:\n\n```bash\nfly launch --copy-config --no-deploy   # first time: creates the app + volume\nfly deploy\n```\n\n**Data flows in by itself.** Each sim exposes a token-protected\n`/export/db` route, and the hub pulls all three feeds every\n`SYNC_INTERVAL_MIN` minutes (default 30) into its volume — no CLI, no\nmanual uploads. One-time setup, all in the Fly dashboard (each app →\nSecrets):\n\n1. Generate a secret per sim and enter it in two places — the sim and the\n   hub:\n\n   | Value | Sim app → secret name | vroomtv → secret name |\n   | --- | --- | --- |\n   | secret #1 | hybrid-baseball → `EXPORT_TOKEN` | `BASEBALL_SYNC_TOKEN` |\n   | secret #2 | viperball → `EXPORT_TOKEN` | `VIPERBALL_SYNC_TOKEN` |\n   | secret #3 | tennis-team-manager → `EXPORT_TOKEN` | `TENNIS_SYNC_TOKEN` |\n   | secret #4 | — | `SYNC_TOKEN` (guards the manual `/sync` URL) |\n\n   (Using one value everywhere also works: set it as each sim's\n   `EXPORT_TOKEN` and as `SYNC_TOKEN` on vroomtv — the per-sport tokens\n   fall back to `SYNC_TOKEN`.)\n2. Redeploy the three sims (their export routes ship in each repo) and the\n   hub.\n\nThat's it. To force an immediate refresh, open\n`https://\u003cyour-hub\u003e/sync?token=\u003cSYNC_TOKEN\u003e` in a browser — it reports\nper-sport results. Any unconfigured or unreachable sport shows a\nplaceholder, never an error.\n\n(`scripts/sync-dbs.sh` remains as an alternative for fly-CLI users.)\n\nThis won't work on static/serverless hosts (Netlify, GitHub Pages, Vercel's\nstatic mode): the hub is a long-running Flask server that reads SQLite files\nfrom local disk.\n\n## Routes\n\n| Route | Page |\n| --- | --- |\n| `/` | Front page — recent scores across all sports |\n| `/standings` | Standings, every league/season |\n| `/leaders` | Stat leaders (batting \u0026 ERA, rushing, singles match wins) |\n| `/game/baseball/\u003cid\u003e` | Box score + play-by-play |\n| `/game/viperball/\u003csave_key\u003e/\u003cweek\u003e/\u003cmatchup_key\u003e` | Game summary |\n| `/game/tennis/\u003cgtt\\|ncaa\u003e/\u003cid\u003e` | Dual line scores |\n\n## Repo layout\n\n```\napp.py            Flask routes (thin — rendering only)\nmanage.py         runserver entry point\nadapters/         one read-only DB adapter per sport\nnewsroom.py       placeholder headlines parsed from results + pixel-art SVGs\ntemplates/        Jinja UI: scoreboard strip, front page, news, box scores\nstatic/style.css  the design system (Fontshare: Boska / Zodiak / Switzer)\ndocs/             after-action report (build + verification history)\n```\n\n`docs/aar-vroomtv-sports-hub.md` has the full build history, the schema\naudit against each sim, and what was verified against live data.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarterback%2Fvroomtv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquarterback%2Fvroomtv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarterback%2Fvroomtv/lists"}