echecs

Build chess apps with confidence.
24 packages. Zero dependencies. FIDE compliant.

Core

Start with @echecs/game for full game logic, or pick individual packages for parsing and notation.

@echecs/position

Chess position type and board utilities

@echecs/fen

Parse and stringify FEN chess positions

@echecs/san

Parse, resolve, and stringify SAN moves

@echecs/pgn

PGN parser with comments, variations, and NAGs

@echecs/game

Legal move generation, undo/redo, game-state detection

@echecs/zobrist

Polyglot standard Zobrist hash keys

@echecs/polyglot

Read and query Polyglot opening book files

Engine

@echecs/uci

UCI engine wrapper for Stockfish and others

Ratings

@echecs/elo

ELO rating system following FIDE rules

Tournaments

@echecs/swiss

Swiss pairing and standings following FIDE rules

@echecs/round-robin

Round-robin pairings following FIDE Berger tables

@echecs/tournament

Stateful tournament orchestrator for any FIDE system

Tiebreaks

FIDE-standard tiebreak systems for Swiss and round-robin tournaments. Used by @echecs/tournament or standalone.

@echecs/buchholz

Buchholz tiebreak family (Cut, Median, Average, Fore)

@echecs/sonneborn-berger

Sonneborn-Berger tiebreak

@echecs/progressive

Progressive score tiebreak

@echecs/koya

Koya tiebreak for round-robin tournaments

@echecs/direct-encounter

Direct encounter tiebreak

@echecs/number-of-wins

Win-counting tiebreaks (Wins, Black Wins, Standard Points)

@echecs/average-rating

Average Rating of Opponents tiebreak

@echecs/performance-rating

Performance rating tiebreaks (TPR, Perfect TPR)

UI

@echecs/react-board

React chessboard with drag & drop and animation

@echecs/react-movesheet

Move notation panel with click nav and variations

File Formats

@echecs/trf

FIDE Tournament Report File parser

@echecs/tunx

SwissManager TUNX binary file parser/serializer

Clean APIs, strict types

Every package is TypeScript-first with full type inference

import { Game } from '@echecs/game';
import { parse } from '@echecs/san';

const game = new Game();

// Scholar's mate
for (const san of ['e4','e5','Qh5','Nc6','Bc4','Nf6','Qxf7']) {
  game.move(parse(san, game.position()));
}

game.isCheckmate(); // true
game.turn();        // 'black'