The official chess web-based app of BoldChess.com. It is a responsive web GUI for the Stockfish chess engine, offering analysis, evaluation, and graphical features.
Our mission is to create a modern, mobile-friendly, free, and open-source web-based chess app, powered by the advanced Stockfish chess engine.
A live version is only available for the BoldChess.com paid members. As this is an open-source project, anyone can run it locally without overloading our servers.
- Load your chess position or game using FEN, PGN, or a move list.
- Set up pieces manually in edit mode.
- Browse game history using arrows or the mouse wheel.
- List and display all legal moves on the chessboard.
- Analyze positions and legal moves using the JavaScript version of Stockfish.
- Display an evaluation graph with visual indicators for blunders.
- Open a position or game in a new window via a URL.
- Play against the Stockfish engine, with the ability to set its rating according to your preference.
- Activate/Deactivate a special "Coach Mode" to view the best move and evaluation while playing.
- Customize the appearance of the chessboard.
- Draw arrows or highlight squares on the chessboard.
- Visualize relevant squares based on Stockfish's static evaluation.
- Dark interface with a pitch-black background for OLED screens, improving battery life and user experience.
- Support for PCs, tablets, smartphones, and touch devices.
- Chessboard
- All Moves With Evaluations
- History of Moves
- Evaluation Graph
- Static Evaluation
- Chessboard Editor
- To open your FEN or PGN, copy it to the clipboard and paste it into the input box above the chessboard.
- To browse the game, use the mouse wheel on the chessboard or the arrow buttons.
- To open or hide windows, click on the small icons at the top of the GUI.
- To play against the engine or set its difficulty level, click on the hamburger menu.
- To change the board styling, flip the board, or open it in a new window, click on the hamburger menu.
The application uses an optional .env file for configuration.
| Variable | Description | Default |
|---|---|---|
PORT |
The port the server will listen on. | 3000 |
This project uses Bun for dependency management and as a runtime.
-
Prerequisites:
- Ensure Bun is installed on your system.
-
Repository Setup:
- Clone the repository to your local machine.
- Navigate to the project directory.
-
Dependency Installation:
-
Install the project dependencies:
bun install
-
-
Local Server:
-
Start the local development server:
bun start
-
Access the application at
http://localhost:3000in a web browser.
-
The client is plain ES modules, served straight from public/ with no bundler. main.js is only the
entry point: it wires the DOM to the modules at start up and does nothing else.
public/
main.js start up and DOM wiring only
src/
config.js engine depth limits, starting FEN
state.js mutable app state shared by the UI modules
env.js mobile detection
commands.js the command box: FEN/PGN loading and text commands
chess/ fen.js, rules.js, notation.js, draws.js - no DOM access
engine/ uci.js (worker wrapper), engines.js (lifecycle), analysis.js
eval/ terms-data.js, terms.js, static-eval-list.js
game/ position.js, history.js
ui/ board, moves, graph, menu, panels, arrows, tooltip, layout,
static-view, dom helpers
input/ mouse.js, keyboard.js
Two rules keep this workable:
chess/,eval/andengine/uci.jsnever touch the DOM. That is what makes them testable underbun test, and it is whydoMovetakes its default promotion piece from a provider the app installs at start up rather than reading it from the toolbar itself.- Shared mutable state lives on the
stateobject, not in module-levelletbindings, because ES modules export read-only live bindings.
We use Biome for linting and formatting.
-
Check for issues:
bun run lint
-
Fix issues:
bun run lint:fix
-
Format code:
bun run format
The chess core is verified with perft node counts, FEN and
SAN round-trips, and a snapshot of every classical evaluation term. tests/harness.js is the only
file that knows how the browser code is packaged, so the same suite keeps passing while main.js is
split into modules.
-
Run the suite:
bun test -
Include the slow depth-4 perft (~12s):
bun run test:deep
-
Regenerate the evaluation snapshot (review the diff before committing):
bun run test:update
-
Browser smoke test — loads the app in headless Chromium, drives the input handlers and fails on any console error. Needs a Chromium binary (
CHROME=/path/to/chromiumto point at one):bun run smoke
The app uses Stockfish 18 JS, which utilizes SharedArrayBuffer for multi-threaded performance.
To ensure the engine functions correctly, you must configure the following HTTP headers on your server:
- Cross-Origin-Opener-Policy (COOP): Set to
same-origin - Cross-Origin-Embedder-Policy (COEP): Set to
require-corp - Content-Security-Policy (CSP): Must allow
blob:URLs for the multi-part WASM architecturescript-src 'self' 'unsafe-inline' 'unsafe-eval' blob:connect-src 'self' blob:worker-src 'self' blob:
- COOP/COEP: These headers enable cross-origin isolation, which is required for
SharedArrayBufferto function. This allows Stockfish to use multiple threads for faster analysis.
All three deploy targets read from a single source, security-headers.js:
| Target | File | How it is produced |
|---|---|---|
| Express | server.js |
imports security-headers.js directly |
| Netlify | public/_headers |
generated by bun run build |
| Vercel | vercel.json |
generated by bun run build |
Edit security-headers.js, run bun run build, and commit the regenerated files. CI fails if they
drift (node scripts/generate-headers.js --check).
Read more about SharedArrayBuffer at the MDN documentation.
The application is designed for easy deployment in any standard Node.js/Bun environment.
Running the Server: The main entry point is server.js, which serves the static files in the public directory, eliminating the need for a build process. This simplifies deployment and development.
No Bundler: The client is vanilla JavaScript served straight from public/, so there is no bundling or transpilation step. The build script only regenerates the deploy header files from security-headers.js; the app itself is ready to serve as-is.
We welcome all developers to contribute by adding features or fixing bugs.
This project is licensed under the GNU AFFERO GENERAL PUBLIC LICENSE (AGPLv3).