Follow these matches

New matches start ticked. Untick any you don't want to hear.

Match filter checkboxes

No matches loaded yet.

Matches

Press Start to load matches.

Diagnostics

Announcement log

No announcements yet.

To do

  • P1: add a second snooker.org call with tr=seniors alongside the existing tr=main call so the World Seniors Championship shows up. Currently the worker only fetches t=17&tr=main which filters Seniors out. Tour identifier confirmed as seniors. Also revisit the "World Championship only" filter checkbox - rename or generalise to whatever's the current featured event. Need to add the Seniors event ID to framesToWinTarget, nextRoundMilestone, reachedMilestone, deciderPhrase, and welcomeMessageForToday so the round-aware wording works during Seniors week.
  • P1: add basic pronoun handling so Reanne Evans doesn't get "He took frame X" announcements. Simplest fix: if no nickname is set, fall back to surname rather than pronoun. That sidesteps the problem for Reanne specifically without a data-model change. Cleaner long-term: a per-player pronoun field in the nickname dictionary ({ nickname, pronoun }), defaulting to "he" when missing.
  • P2: add senior-era player nicknames. Jimmy White ("The Whirlwind"), Ken Doherty ("Crafty Ken"), Tony Drago ("The Tornado of Malta"), and check the rest of the Seniors field. The Rocket is already in.
  • P2: persistent header / SPA-style navigation. Currently clicking Info or Contact does a full page reload, which kills the announcer's audio, polling timer, and speech queue. The header (with Start/Stop, settings, current match panel) should stay put when navigating between Home / Info / Contact - only the content area below changes. Recommended approach: progressive enhancement (option C from the discussion) - intercept nav link clicks with JS, fetch the new page's content via fetch(), swap the content area in-place. Falls back to full reload if JS is off. Each page keeps its own worker route for direct URL access. Care needed for: browser back/forward (use history.pushState), per-page inline scripts running on swap (Info/Contact have their own IIFEs - either re-run or skip the script swap and just swap markup), focus management for accessibility (announce route change to screen readers).
  • P3: persistent server-side log of announcements (KV-backed) so we can review what was said when nobody had the page open. Categorise by trigger (score change vs interval vs manual).
  • P4: consider enabling HSTS in Cloudflare SSL/TLS settings. Closes one of the Security Insights warnings. Held off because it's effectively irreversible (browsers cache the policy for the configured max-age) and the marginal protection over "Always Use HTTPS" is narrow. If enabling: start with max-age 1 month, do NOT tick preload, do NOT tick includeSubdomains until thought through.

Tips & credits

Keep this tab open in the background. Your browser must remain open for speech to work, and on mobile the screen may need to stay on.

Data credit: All match data is provided by snooker.org, maintained by Hermund Ardalen. This tool would not exist without his generosity in providing API access.