← All posts
PROJECT
Game Development · PWA · Animation
Chess, without the metrics
Why I built a chess app with no ratings and no streaks—just the board, a hidden drawer, and an engine tuned to my level.
stack React · Python · Stockfish
status live
Chess Without the Clutter
I love chess—not the competitive, metric-tracking, rating-chasing kind of chess, but the casual, conversation-over-coffee kind. The game you play with friends while catching up, where the board is just an excuse to spend time together. I wanted that same casual experience on my phone for those spare moments throughout the day.
The problem? Every chess app I found was either bloated with features for serious players—opening databases, performance analytics, puzzle trainers—or so old and outdated it felt like it was pulled from 2008. I didn't need all those bells and whistles. I just wanted a clean, elegant chess app that worked well and got out of the way.
So I built one—a Progressive Web App designed for casual play, thoughtful design, and nothing more.
Just the Game, Nothing Else
Opening the app skips straight to the game. No menus to tap through, no options to configure—just the board, ready to play. Move pieces by dragging or tapping, whichever feels natural. If you're in check, a quiet indicator appears above the board. Nothing else demands your attention unless you go looking for it.
A slim drawer rests at the bottom of the screen, out of the way until you need it. By default, it shows four quick-access buttons: new game, undo move, show hint, and show last move—the things you actually reach for mid-game.
The interface should disappear. Your attention belongs on the game, not the app.
Drag the drawer up and it springs open to reveal a fuller set of options—change player color, change theme, change difficulty, and view move history. Tap one and the drawer closes, but the collapsed toolbar transforms: the four default buttons are replaced by controls for whatever you picked. Tap "Change Difficulty" and a slider takes over the toolbar; tap "Done" and the original four snap back into place. It's a small trick, but it lets the app carry real features without ever feeling cluttered.
Building with React and Stockfish
The app is a React Progressive Web App built with Create React App. The chess logic comes from two excellent libraries: react-chessboard for rendering a highly customizable board, and chess.js for managing game state, legal moves, and win conditions.
Everything else is orchestrated by a custom hook I built called useGame. This hook provides the React components with all the game state they need—current position, legal moves, check status, whose turn it is—along with functions to interact with the game like making moves, requesting engine analysis, and resetting the board.
The Stockfish Backend
Stockfish is the most powerful open-source chess engine in the world. It's written in C++, which means it can't run directly in a browser without compiling to WebAssembly—a path that felt overly complex for this project. Instead, I built a small Python service using FastAPI to act as a bridge between the browser and Stockfish.
The API has just one endpoint. The frontend sends the current game state in FEN notation—a compact text format that encodes the entire board position. The backend passes that to Stockfish, waits for it to calculate the best move, and returns the result. The engine is tuned to play at my level, which means I win about half the time.
Stockfish plays at exactly my skill level—challenging enough to keep me engaged, beatable enough to stay fun.
Progressive Web App
The app is a PWA, which means it can be installed on your home screen and feels like a native app. The board and game logic work offline since chess.js runs entirely in the browser. The only time you need a connection is when requesting a move from the Stockfish backend.
Tech Stack
React
chess.js
react-chessboard
Python
FastAPI
Stockfish
What's Next
The app already covers the basics you'd want in a casual chess game—viewing move history, asking for a hint, changing difficulty, swapping sides. But there are more bells and whistles that could make it even more delightful, like setting up custom board positions to play out a specific scenario.
Eventually, it would be interesting to add multiplayer—playing real people instead of just the engine. The challenge isn't adding functionality; it's doing so in a way that preserves the elegant, uncluttered feel of the current design.
The challenge isn't adding features—it's adding them without making the app feel bloated.
What I Learned
This project taught me a lot about animation and polish. Getting the drawer to feel natural—the spring as it opens, the morph as the collapsed toolbar swaps in new controls, the snap back to default—took real time with timing curves and visual weight. The board transitions had to be smooth and deliberate, not jarring. These details take time, but they're what separate a functional app from an enjoyable one.
It was also my first time deploying a React app alongside a backend service. I learned to deploy the frontend on AWS Amplify and the Python backend on Google Cloud Run—both effectively free for this scale. And working with Stockfish gave me my first exposure to chess engines, FEN notation, and wrapping a C++ binary in a REST API.