Skip to content

Sports Scores

P3DROVFX edited this page Oct 12, 2026 · 1 revision

Sports Scores

Live scores and fixtures for the leagues and clubs you follow, from ESPN's public scoreboard API — in the bar, the dock, the lock screen, the Dynamic Island, the launcher, the Timetable (as read-only games) and the AI assistant. It is one data source (SportsService) with several independent consumers: turning off the bar widget does not turn off the dock widget, and no consumer means no request at all.

No API key is needed. Data comes from site.web.api.espn.com / site.api.espn.com (/apis/site/v2/sports/<sport>/<league>/scoreboard and …/summary?event=<id>). ESPN's API is unofficial; leagues occasionally change slugs or go missing — the settings page links the API docs for that reason.

Quick start

  1. Settings → Bar → Sports (the Sports Tracker page) → Enable sports tracker.
  2. Under Monitored leagues switch on the leagues you want (the defaults are Brasileirão, Premier League and Champions League) or Add new league with ESPN's identifiers, for example sport soccer, league esp.1.
  3. Optionally type team names in Preferences filter (comma separated, exact names: Real Madrid, Arsenal) to show only those clubs.
  4. The widget appears in the bar; hover it for the popup, click it to cycle through the games.

What each surface does

Surface Behaviour Switch
Bar A compact scoreboard: crests, score and status of the "current" game; two styles, Default and Expressive. Hover (or click, in click-to-show mode) opens a popup with up to Max cards in popup match cards. Click the widget to move to the next game. bar.sports.enable
Dock A horizontal scoreboard widget with the same data and a tooltip-style popup that slides out of the dock; click to cycle dock.enableSportsWidget
Lock screen A pill at the top, beside Now Playing: both crests, the score beside each, and a status pill — highlighted in the accent colour while the game is live; click to cycle lock.sports (Lock Screen settings)
Dynamic Island A sports source/activity on the island dynamicIsland.widgets.sports
Launcher A Sports panel with today's games for the leagues of your choice search.modules.sports (enable, lookaheadHours, leagues)
Timetable Read-only games on their day, with a rich match page — see [[Calendar and Timetable Calendar-and-Timetable]]
AI The assistant can look up scores and fixtures for any ESPN league, not only the monitored ones [[AI Integration

The compact windows decide which games are "current": a match is shown from showBeforeHours (default 12) before kick-off until showAfterMinutes (180) after it ends, so a finished game stays visible for a while. Games are ordered by status (live first), or by your own order (customOrder); the game on the widget is remembered across restarts (activeGameId).

How it fetches (and why it is cheap)

  • Reference-counted. The service runs only while there is a consumer: the bar widget, the dock widget, the lock screen while the lock surface is active, a desktop widget, the Timetable's sports mode, or the launcher/AI for a moment. The launcher and AI keep their own subscriber counts and never start the compact polling loop; an AI query never changes the game shown on the bar or writes a preference.
  • Polling. One scoreboard request per monitored league every updateInterval seconds (default 60) while a compact consumer is enabled. Requests are cancelled when their consumer goes away, and have a finite timeout.
  • Timetable range. For the Timetable the service asks for a whole month per league (scoreboard?dates=…), compacts it into a small record per game, and caches it atomically at ~/.local/state/quickshell/user/generated/sports.json (schema 2, 1 is still readable). The cache is only parsed while the Timetable needs it. While the visible range includes today, the compact timer is paused and the range's own timer shares the query. A forced refresh at the configured interval only happens when a game is live or inside its probable window; when you are looking at a match page, its summary is refreshed too, with a shorter TTL in the two hours before kick-off to catch late line-ups.
  • Normalization. ESPN's arrays are not evidence of content (rosters, boxscore.teams and leaders can hold empty team envelopes), so SportsDetailsHelpers.js flattens each payload once into plain rows before any QML list sees it, and the match page shows an empty state only when those rows are empty.
  • Isolation. Games never enter khal, have no UID and cannot be edited, dragged or deleted.

The match page

Opening a game in the Timetable's rail shows what the sport provides: line-ups, score and statistics, leaders, a timeline with commentary and key events, venue and address, broadcast, referees, recent form, head to head, news, videos, odds, injuries, standings and links. Key events become individual rows with a clock pill and dividers. The month view marks games with filled pills (sports_score); the week view puts a count pill under the weekday that opens a games-only list so simultaneous matches never overlap.

Configuration (Config.options.bar.sports)

Key Default Meaning
enable on The bar widget (and the tracker)
monitoredLeagues Brasileirão, Premier League, Champions League List of {sport, league, name, enabled}; league ids are ESPN slugs such as bra.1, eng.1, uefa.champions
teamFilter "" Comma-separated exact club names
updateInterval 60 Seconds between scoreboard requests
maxCardsPopup 4 Cards in the popup
showBeforeHours / showAfterMinutes 12 / 180 The window around a game
customOrder, activeGameId — Remembered order and current game
showBRA, showCL, showEPL… legacy Older per-league toggles; the list above is authoritative
colorMode primary Bar colour role

Bar style: bar.styles.sports (default / expressive).

Under the hood

Piece Role
services/SportsService.qml Subscribers, scoreboard / schedule / summary requests, normalization, compact and timetable projections, cache
services/SportsServiceHelpers.js Pure helpers
modules/ii/bar/widgets/sports/, modules/ii/bar/popups/sports/SportsPopup.qml Bar widget (both styles) and popup — the popup controller is created lazily on hover
modules/ii/dock/DockSportsWidget.qml, widgets/DockSportsPopup.qml Dock
modules/ii/lock/LockSurface.qml Lock-screen pill
modules/ii/dynamicIsland/core/sources/SportsSource.qml Island
modules/ii/overview/SportsPanel.qml Launcher panel
modules/ii/cheatsheet/timetable/SportsEventDetails.qml, SportsDetailsHelpers.js Match page
services/ai/integrations/AiSportsIntegration.qml Allow-listed ESPN routes for the AI

Related pages

← Back to Home

Clone this wiki locally