AI Chess Web App V2 with Stockfish
Try it out below!
Last Updated: 04/18/25
Introduction
This is Version 2 of my AI Chess web app โ a major upgrade from the original release. It now supports multiple AI engines, including Stockfish 17, Minimax with alpha-beta pruning, a Greedy bot, and a Random bot. The app has been rebuilt for better performance, improved code structure, and enhanced flexibility.
This version also introduces in-browser WebAssembly (WASM) integration and runs in a containerized environment based on Ubuntu 20.04. The frontend is built using React and Node.js, making it a modern, scalable, and responsive chess-playing experience.
WASM + Stockfish Integration
The highlight of this version is seamless integration with Stockfish 17, one of the strongest open-source chess engines in the world, compiled to WebAssembly (WASM) for in-browser execution.
Learning WASM Integration
I learned how to compile C++ code to WASM using Emscripten, a toolchain that converts C++ source files into .wasm binaries along with a JavaScript bridge to load and interact with them in the browser. WASM allows near-native execution speeds and avoids sending data to a backend server โ everything runs securely in the client.
That said, WASM compilation is tricky. It's easy to misconfigure build flags or break threading support, and debugging the resulting binary is difficult since you're operating at a low level. After experimenting with custom builds, I decided to rely on a robust, open-source precompiled version from a community-backed repo:
๐ https://github.com/nmrugg/stockfish.js
Iโm currently using the single-threaded build:
โ Simple and lightweight
โ Compatible across all browsers
โ No multi-core support (compared to the multi-threaded version with PThreads and SharedArrayBuffer)
This version still delivers excellent performance for short move times (1โ4 seconds per move), and is perfectly suited for casual or intermediate online play.
Stockfish 17 โ A Powerful Engine
Stockfish 17 is a state-of-the-art chess engine used by professionals and hobbyists alike. Even with just a few seconds of compute time, it evaluates millions of positions using techniques such as:
Bitboards: Efficient internal board representation for rapid move generation.
Alpha-Beta Pruned Minimax: Reduces the search tree dramatically to focus on promising moves.
Transposition Tables: Caches previously seen positions to avoid redundant work.
Static Exchange Evaluation (SEE): Assesses whether exchanges result in material gain or loss.
Late Move Reductions and Null Move Pruning: Aggressive heuristics to speed up deeper analysis.
Endgame Tablebases: Exact solutions to specific endgame positions.
Itโs incredibly strong โ even with only 2โ3 seconds of search time, Stockfish is a difficult opponent to beat.
AI Opponents
The app provides four distinct AI opponents with different play styles:
๐ง Stockfish 17 (Very Hard Opponent)
Uses advanced pruning, search heuristics, and evaluation techniques.
WASM-compiled and runs entirely in-browser.
Difficulty is controlled by limiting move time (1โ4 seconds).
Makes world-class decisions and punishes tactical errors effectively.
๐งฎ Minimax Bot (Normal Opponent)
Implements a Minimax algorithm with Alpha-Beta pruning.
Search depth is adjustable from 1โ4 plies (half-moves).
Evaluation function assigns values to each piece: p=1, n/b=3, r=5, q=9, k=1000.
Designed to balance attack and defense while managing performance.
How Alpha-Beta Pruned Minimax Works:
Minimax simulates all possible moves to a given depth, alternating between the AI (maximizing player) and the human (minimizing player).
Alpha is the best score the maximizer can guarantee so far.
Beta is the best score the minimizer can guarantee so far.
If a branch canโt possibly improve the outcome, itโs pruned โ saving time and compute cycles.
This makes Minimax efficient enough to offer reasonable play without overwhelming client resources.
โ๏ธ Greedy Bot (Reckless Opponent)
Prioritizes capturing pieces every turn.
Falls back to random moves if no captures are available.
Fun to play against, but highly predictable.
๐คช Random Bot (Silly Opponent)
Selects completely random legal moves.
Best suited for beginners or lighthearted games.
App Features
AI Engine Selector: Choose between Stockfish, Minimax, Greedy, or Random bots.
Difficulty Control: Adjust move time (for Stockfish) or search depth (for Minimax).
Color Toggle: Play as either White or Black. The AI plays the opposite color.
Interactive UI: Drag-and-drop or click-to-move with highlighted legal moves.
Responsive Layout: The board resizes dynamically for desktop and mobile.
Game Feedback: Indicates whose turn it is, whether AI is thinking, and endgame results.
Auto Promotion: Pawns promote to queens automatically for simplicity.
Restart Anytime: Reset the game instantly with a single click.
Development Environment & Deployment
Environment
Ubuntu 20.04 + WSL: Development and Git operations done through WSL on Windows.
Node.js + React: Full frontend application written in modern React.
Docker: Used Docker Dev Containers for consistent and secure local builds.
Deployment
GitHub Pages: Fast and free static site hosting for public deployment.
Public Assets: WASM files and workers are served from the public folder and loaded in the browser at runtime.
Pair Programming with LLMs
ChatGPT (GPT-4o)
ChatGPT was used extensively in both v1 and v2 of this app. It helped me:
Architect the app structure
Write reusable React components
Debug stubborn AI bugs
Optimize minimax logic and WASM usage
Refactor code for clarity and performance
Its ability to engage in interactive dialogue and remember project-wide context made it an indispensable coding partner โ especially when tackling complex features like multithreaded Web Workers or debugging WASM loading issues.
While ChatGPT has limitations (especially around memory limits and needing explicit correction sometimes), it massively boosted my productivity.
GitHub Copilot
Copilot was only used during Version 1 of the app. It was helpful for:
Quick scaffolding
Boilerplate suggestions
However, its lack of project-wide awareness and tendency to offer off-topic completions made it less useful during the more complex work in Version 2.