🎮 Beta Gamer

Tic-tac-toe — Spectate

Any active PvP (non-bot) Tic-tac-toe game can be watched in real time. No session token required.

List live games

const res = await fetch('https://api.beta-gamer.com/v1/rooms?game=tictactoe');
const { rooms } = await res.json();

// rooms: [{ roomId, players: [{ id, username }], moveCount }]

Connect as spectator

import { io } from 'socket.io-client';

const socket = io('https://api.beta-gamer.com/tictactoe', {
  path: '/socket.io',
  transports: ['websocket', 'polling'],
});

socket.on('connect', () => {
  socket.emit('game:spectate', { roomId: 'room_abc123', username: 'Spectator' });
});

socket.on('game:spectate:joined', ({ players, board, currentTurn, moveHistory }) => {
  // board is ('X'|'O'|null)[] of length 9
});

socket.on('game:move:made', ({ board, currentTurn, position, mark }) => {
  // update board
});

socket.on('game:over', ({ winner, reason, winningLine }) => {
  // game ended — winningLine is number[3] or null
});

React SDK spectate example

import { useEffect, useState } from 'react';
import { io } from 'socket.io-client';

export default function SpectateRoom({ roomId }: { roomId: string }) {
  const [board, setBoard]         = useState<('X'|'O'|null)[]>(Array(9).fill(null));
  const [players, setPlayers]     = useState<any[]>([]);
  const [currentTurn, setCurrentTurn] = useState(0);
  const [winningLine, setWinningLine] = useState<number[]|null>(null);

  useEffect(() => {
    const socket = io(window.location.origin + '/tictactoe', {
      path: '/api/socket/io',
      transports: ['websocket', 'polling'],
    });

    socket.on('connect', () => {
      socket.emit('game:spectate', { roomId, username: 'Spectator' });
    });

    socket.on('game:spectate:joined', ({ players: p, board: b, currentTurn: t }) => {
      setPlayers(p);
      setBoard(b);
      setCurrentTurn(t);
    });

    socket.on('game:move:made', ({ board: b, currentTurn: t }) => {
      setBoard(b);
      setCurrentTurn(t);
    });

    socket.on('game:over', ({ winningLine: wl }) => {
      if (wl) setWinningLine(wl);
    });

    return () => { socket.disconnect(); };
  }, [roomId]);

  // Render a read-only 3×3 grid — no click handlers
  return null;
}

Event reference

EventDirectionPayload
game:spectate→ server{ roomId, username }
game:spectate:joined← server{ roomId, players, board, currentTurn, moveHistory }
game:move:made← server{ position, mark, board, currentTurn }
game:over← server{ winner?, reason, winningLine? }
💡 Only PvP games (no bots) are listed. Bot games are excluded from the spectate lobby.
Beta Gamer GaaS API — questions? support@beta-gamer.com