Live scoreboard with team colours
The question: what is on today, who is winning, and can it look like each team? A scoreboard widget for a site, a newsletter or a bot needs three things: the games, each team's mark, and two colours per game that read on the page and do not clash with each other.
The workflow: sportsdataverse-js fetches ESPN's scoreboard (sdv.nba.espnNbaScoreboard({ parsed: true }) in Node). In your browser this page does the same thing with a plain fetch of the same ESPN URL and sdv-js's own parser, parseEndpoint("espn", "scoreboard", raw), so the rows have the same columns either way: one row per game, with each side's ESPN id, abbreviation and score. sdvplot then gives every game its colours: matchupColors picks a pair that reads on this page and stays apart (a CIEDE2000 distance of at least 20), onColor picks black or white text on each, and logoUrlSync gives each team's mark. ESPN's team ids resolve in sdvplot as they are, so there is no lookup table.
By default the page draws a committed snapshot: the NBA's 17 March 2024 slate. Tick Fetch live from ESPN to fetch today's games for the league you pick; your browser makes the request, the page's build never does. Each card links to the win-probability scrubber (football) or the game dashboard (basketball) for that game.
What to take from it
- The browser can be the client. ESPN's site API sends
Access-Control-Allow-Origin: *, so a page can fetch it directly, with no proxy and no server. One catch for anyone testing it headless:site.api.espn.comleaves that header out when the user agent saysHeadlessChrome, so an automated check must send a normal Chrome user agent. - One parser, two runtimes. sdv-js's parsers are browser-safe (
sportsdataverse/parsers); this page uses that bundle, vendored at a pinned commit and sha256. The rows a Node script gets fromespnNbaScoreboard({ parsed: true })and the rows this page draws are the same rows. - Pairs, not single colours. Two teams' primary colours often clash (two reds, two navies).
matchupColorschecks the pair against the page's background and against each other, falling back to a secondary colour or a lighter shade only when it must.
Script it in Node: sdv-js's nightly scores card draws the same slate as a PNG with socialCard and posts it from a GitHub Action.