← 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 interface on a mobile device.

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.

The drawer opened during a game.
Changing the player's color.
In the middle of a chess game.
The entire interface is the board, with a subtle dynamic drawer for everything you might need while playing chess.

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.

collapsed
Drawer collapsed during a game
open
Drawer open with more options
Open the drawer to see more bells and whistles.

Key Features

Built for casual players who value simplicity and craftsmanship:

Simple Interface

No hoops to jump through, just the board and your next move. The interface and its controls get out of the way so you can focus on the game.

Thoughtful Animations

The drawer spring, smooth piece movements, and board transitions were crafted with attention to timing and natural motion. It's playful and satisfying, just like a game should be.

Progressive Web App

Install it on your home screen, and it behaves like a native app. Everything is optimized for how you would want it to feel as a full screen mobile app.

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.

React Frontend

react-chessboard

Custom animations

PWA manifest

chess.js

useGame hook

Game state
Move response

Python Backend

FastAPI

Single endpoint

Stockfish

Difficulty tuning

Fig. 1 — Frontend handles all game logic and UI, backend wraps Stockfish to provide engine analysis

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.

Try Chess

Play a quick game against the Stockfish engine in this fast-loading, responsive chess web app.

Let's talk.

Open to new roles, projects, or a chat about code and flying.