The story of a game for the commentators, and a search box that suggests where to start
The stream's commentators are handed the game one play at a time: a shot, a steal, a rebound. Plays on their own miss the shape of a game, the moment it is level again or one team takes over. The facts they are handed now carry that too.
Ties, lead changes and runs
After every score the feed compares the scoreboard before and after. If the game was not level and now is, that is a tie. If the lead passed from one team to the other, that is a lead change. Going from a tie into a lead is not counted as a change, since nobody's lead was taken. And once one team has scored 8 or more points while the other has scored none, that is a run, told again at every score it grows by.
if (before !== 0 && after === 0) out.push({ kind: "tie", ...base });
else if (before * after < 0) out.push({ kind: "lead_change", from_team: 1 - team, ...base });
if (run.points >= RUN_MIN) out.push({ kind: "run", run_points: run.points, ...base });
All of it is read from the same points the scoreboard shows, so the story can never disagree with the score on screen. Each of these facts carries only the teams' names and numbers.
Somewhere to start
The search box on the front page used to sit empty until you typed. Now, while it is empty, it offers four places to start: the newest post, the team at the top of the standings, the league's points leader and the game of the season. Each is taken from the same index the search reads, so a suggestion always lands on a page that exists. If the index cannot back one of them, that one is simply left out. Start typing and the suggestions give way to the results.