Live scoreboard widget

A drop-in, embeddable scoreboard for any sport. Sub-second updates over WebSocket, zero polling from your end.

What you'll build

A small Next.js page that subscribes to a live channel, renders scores, and can be embedded as an iframe in any site.

Wire up the WebSocket

'use client';
import { useEffect, useState } from 'react';

export default function Scoreboard({ channel }: { channel: string }) {
  const [games, setGames] = useState<Record<string, any>>({});

  useEffect(() => {
    const ws = new WebSocket(
      `wss://stream.sportapi.io/v1?token=${process.env.NEXT_PUBLIC_SPORTAPI_RK}`
    );

    ws.onopen = () => ws.send(JSON.stringify({ type: 'subscribe', channel }));
    ws.onmessage = (e) => {
      const msg = JSON.parse(e.data);
      if (msg.type === 'update') {
        setGames(prev => ({ ...prev, [msg.data.game_id]: msg.data }));
      }
    };

    return () => ws.close();
  }, [channel]);

  return (
    <div>
      {Object.values(games).map(g => <GameRow key={g.game_id} game={g} />)}
    </div>
  );
}

Render scores

Each GameRow shows team, score, period, and clock. Keep it minimal — the magic is that the data updates itself.

Embeddable iframe

Wrap the page at /embed/scoreboard?channel=nba.scores.live and ship:

<iframe
  src="https://yourapp.com/embed/scoreboard?channel=nba.scores.live"
  width="100%" height="400" frameBorder="0"
/>

Use a restricted key (rk_…) on the embed so the public can't scrape and reuse it elsewhere.