I like watching highlights the morning after a game, but YouTube puts the final score in the title and the thumbnail. This collects highlight videos from each league's official channel and shows them without spoilers.
What it does
- A morning brief: yesterday's games across every sport on one page.
- A feed per sport: MLB, NBA, NFL, college football, the Premier League, La Liga, the Bundesliga, the Champions League and the Europa League, with infinite scroll by day.
- My teams: favorite teams and conferences filter the brief and the feeds, and college football has a Top 25 chip.
- Each team's record going into the game, beside its name ("Georgia 5-1 vs Alabama 6-0"), to help me pick which game to watch first. Soccer reads won-drawn-lost.
- Watched markers, so I know what I've already seen.
How it's built
A Rails 8 rewrite of my original Node/Express version (kept under legacy/).
- A fetcher service queries the YouTube Data API per sport, keeps only actual game highlights (by channel and title keywords), and recovers each game's date from its title.
- Each sport has its own sources. A league with one official channel is simple. College football is not: each network only recaps the games it aired, so the fetcher reads four networks' channels and three conference channels. When two channels post the same game, a team catalog matches the teams in both titles and the feed keeps one recap.
- Title patterns follow the season. MLB's postseason titles carry a series name and a game number in place of the regular-season wording. One pattern covers both and still requires a single game with a date, so whole-series recaps stay out.
- Records that don't spoil. Each schedule sync counts every team's wins and losses from the season's results, in order, and stores the record each team took into each game. Scores are never stored. A record that includes a team's latest result would give that result away, so a team's next game shows no record until three days after its previous one (one day for MLB and the NBA). Once a game has started, the record it started with is safe to show.
- A Solid Queue job runs every 30 minutes and stores new videos, de-duplicated by URL. There's no separate worker host; the queue runs inside Puma.
- A
DayFeedservice buckets games into local days for both the brief and the scrolling feed. - The front end is Turbo plus a couple of Stimulus controllers. There's no build step: assets go through Importmap and Propshaft.
Playback
Highlights open on YouTube in a new tab. Leagues restrict embedding on many of their highlight videos, so linking out is the one approach that works for every clip.
Deployed to the Mac mini behind a Cloudflare tunnel, and redeployed automatically on every push.