home/ work/Basketball Scoreboard
Creator · 2024 · Sports tech

Basketball Scoreboard

A real-time basketball scoreboard plugin for WordPress — operator panel, live broadcast overlay, and OCR-assisted score reading from a camera feed. Built to run in a gym with no guarantees on the network.

Role Creator
Year 2024
Sport Basketball
Platforms web (admin) · web (overlay)
Domain Sports tech · Real-time · Broadcast
State sync interval
500 ms
polling, change-gated
Input modes
2
manual + OCR camera
Shot clock presets
14s / 24s
FIBA / NBA rules
Foul tracking
5 per team
colour-coded dots

Overview

I built this for basketball. KK Jesenice needed a scoreboard overlay that an operator could run from a WordPress admin panel and project live onto the gym wall or pipe into a streaming setup. The constraint was real: a basketball gym is not a server room. You get a laptop, a projector, and a Wi-Fi router that may or may not survive the match.

The plugin has two surfaces. The operator panel lives in the WordPress admin — it shows quarter, game clock, shot clock, scores, fouls, team logos, and league name. Every field updates every 500 milliseconds over AJAX, but only when something has actually changed; the diff-guard keeps the link quiet on a congested gym network. The overlay page polls the same endpoint and repaints the DOM. Both run on the same codebase; the script detects wp-admin body class to decide which direction to run.

The shot clock is not just a display — it counts down in-browser at 1 Hz, with 14 s and 24 s reset presets wired to single buttons for FIBA and NBA rules. The game clock works the same way. Fouls are tracked per team as five coloured dots: orange through four, red at five. At the resolution and distance of a gym display, colour reads faster than a number.

There is also an OCR mode. If the club already has a physical scoreboard, an operator can point a camera at it (or upload a photo), draw bounding rectangles around the score, clock, and quarter sections, and let Tesseract.js extract the values. Each region has independent preprocessing — threshold, contrast, grayscale toggle, noise removal — because a red LED segment and a white LCD digit need completely different treatment. Konva.js handles the canvas region interaction.

Architecture

~/scoreboard/architecture/system-map.svg
01 — OPERATOR INPUTManual Panelscore · fouls · clocksOCR Camera / ImageTesseract.js · Konva.jsState LayerWordPress · AJAX · Transientssave on change · 500 ms poll · nonce-guarded02 — DISPLAY OUTPUTSOverlay Page/overlay/[slug] · shortcodeOBS Browser Sourcestream · projector03 — IN-BROWSER CLOCKSGame ClocksetInterval 1 Hz · mm:ssShot Clock14s / 24s presets · per-teamWordPress plugin · PHP transients · jQuery AJAX · change-hash guard · rewrite rules · shortcode renderer04 — PLATFORM

Reading the diagram: Two input paths (manual panel and OCR camera) write into a shared state layer — WordPress transients served over AJAX with a 500 ms poll and a diff-guard so idle matches don’t chatter. The overlay page at /overlay/[slug] consumes that endpoint and repaints only on change; it works as an OBS browser source for streaming. In-browser clocks (game clock and per-team shot clocks) run client-side at 1 Hz so a network hiccup doesn’t freeze the display.

Scoreboard display

~/scoreboard/overlay/display-mockup.svg
FANTJE U14 · 1.B SKL · POKAL SPAR3Q07:24KK JESENICE54KK TRIGLAV49

Overlay layout: quarter + game clock on the left, team names with foul dots, and large score numerals. Foul dots are colour-coded — orange through four, red at five — readable at projector distance without squinting at digits.

03 What I delivered · challenges solved

Six things shipped,
three hard ones solved.

Key contributions

  • Built the entire WordPress plugin from scratch — custom post type, admin operator UI, AJAX state layer, and public overlay renderer.
  • Implemented dual input modes: a manual scoreboard panel with ±1 / ±2 / ±3 score buttons and a live OCR path via camera or uploaded image.
  • OCR pipeline uses Tesseract.js on a Canvas 2× up-scaled region with per-region threshold, contrast, and grayscale preprocessing controls.
  • State is persisted via WordPress transients and polled every 500 ms — update is only written when data actually changes, keeping the network quiet.
  • Game clock counts down in-browser; shot clock supports 14 s and 24 s reset presets matching FIBA/NBA rules.
  • Foul dots render in orange up to 4, turn red at the 5th — visible at broadcast distance without reading numbers.
  • Overlay exposed at /overlay/[slug] via custom rewrite rules; embeddable as a shortcode for OBS browser source.

Challenges solved

  • Gym Wi-Fi is unreliable — AJAX polling with a change-hash guard keeps the overlay responsive without hammering the server on a slow link.
  • Scoreboard displays at camera distance; foul count has to read as colour, not digits — designed the five-dot system accordingly.
  • OCR from a physical scoreboard camera needs preprocessing per-region (different brightness zones, LED vs. LCD digits) — tunable sliders per marked region rather than one global threshold.
The constraint wasn't the code — it was the environment. A gym has a projector, a laptop, and Wi-Fi that might work. The system had to be solid enough that none of that mattered.
Davor Majc, Creator

Client

Communication was fast and professional. Everything we agreed on was delivered on time, and design suggestions came with real taste. Numen will be our first choice for future projects.
Dejan Čopič, KK Jesenice
04 Tech stack

What's under the hood.

JavaScriptPHPjQueryWordPressTesseract.jsKonva.jsCanvas APIAJAX
Let's talk

Ready to fix, build,
or scale?

30 minutes, with me personally. I'll read your system like a log file and tell you what I'd do first. No pitch deck, no sales funnel.

Davor Majc, founder, Numen

What you get on call
→ a one-page diagnosis
→ 2–3 fix shapes, ranked by leverage
→ rough cost + timeline for each
→ yes/no — am I the right fit
+386 40 828 474 · Blejska Dobrava, SI