complete typescript api client with:
PlayerColor = "white" | "black"
GameStatus = "active" | "finished"
CreateGameRequest, CreateGameResponse
SubmitMoveRequest, MoveResponse
GameStateResponse, AnalysisLinegetHealth() // check backend status
createGame(elo, color) // start new game
submitMove(gameId, moveUci) // send player move
getGameState(gameId) // get current board
finishGame(gameId) // end game, get pgn- ✅ configurable base url from
VITE_API_BASE_URLenv var - ✅ custom
ApiErrorclass with status codes - ✅ proper error handling and network error messages
- ✅ json content-type headers
- ✅ utility functions:
formatEvaluation(),getEvaluationColor()
import { createGame } from './lib/api';
const handleStartGame = async () => {
try {
const game = await createGame(1200, "white");
console.log(game.game_id); // "abc-123-..."
console.log(game.elo_bucket); // 1200
console.log(game.player_color); // "white"
// navigate to game board...
} catch (error) {
if (error instanceof ApiError) {
console.error(error.message, error.status);
}
}
};import { submitMove } from './lib/api';
const handleMove = async (gameId: string, move: string) => {
try {
const response = await submitMove(gameId, move);
console.log(response.engine_reply_uci); // engine's move
console.log(response.eval_player_cp); // evaluation from player's pov
console.log(response.top_moves); // top 3 suggested moves
} catch (error) {
console.error(error);
}
};import { getGameState } from './lib/api';
const loadGame = async (gameId: string) => {
const state = await getGameState(gameId);
console.log(state.current_fen); // current position
console.log(state.moves_uci); // all moves: ["e2e4", "e7e5", ...]
console.log(state.status); // "active" or "finished"
};backend returns dual perspective evaluations:
{
eval_white_cp: 150, // white's perspective (+ = white better)
mate_white: null,
eval_player_cp: -150, // player's perspective (+ = player better)
mate_player: null,
}use eval_player_cp for ui - it's always from the player's perspective regardless of color choice.
utility function:
import { formatEvaluation } from './lib/api';
formatEvaluation(150, null) // "+1.5"
formatEvaluation(-200, null) // "-2.0"
formatEvaluation(null, 3) // "M3"# frontend/.env
VITE_API_BASE_URL=http://localhost:8000/api// if you need to override
const customUrl = "https://api.production.com/api";
// modify api.ts API_BASE_URL constantimport { getHealth, createGame } from './lib/api';
// test health
const health = await getHealth();
console.log(health.status); // "ok"
// test game creation
const game = await createGame(1200, "white");
console.log(game);# terminal 1 - backend
cd backend
uvicorn theo_api.main:app --port 8000
# terminal 2 - frontend
cd frontend
npm run dev-
wire up experience select (when ready):
- import
createGamefunction - add elo values to levels
- call api on button click
- navigate to game board
- import
-
build chess board component:
- display board from fen
- handle piece moves
- call
submitMove() - show
eval_player_cp - display top moves
-
add dependencies:
npm install react-router-dom npm install chess.js # for move validation
frontend/src/lib/api.ts # complete api client
commit message:
add typescript api client for backend integration
- full type definitions matching backend schemas
- api functions: createGame, submitMove, getGameState, finishGame
- error handling with custom ApiError class
- utility functions for formatting evaluations
- configurable base url from env var
everything is ready for integration! 🚀