CKWatson: A puzzle game that simulates chemical kinetics

8 hours ago 1

JavaScript Style Guide  black pre-commit uv Coverage Status License

CKWatson is an educational game about chemical kinetics. The game is organized in "puzzles". Each puzzle starts off with a few reactants. Within a given set of all substances possibly present, the player's goal is to figure out all elementary reactions involved with the chemical process when the reactants are mixed together.

Elementary [reactions], my dear Watson!

image

(live demo)

Binary dependencies. This project uses uv as the package manager and just for convenience. Optionally, Redis enables server-sent events (SSEs) and more production-ready rate-limiting & caching. If you don't have them available yet, are on macOS, and have installed Homebrew, you can install both binaries in one go this this command:

brew install just uv redis

To clone the repository and initialize the virtual environment, run these commands:

git clone --recurse-submodules https://github.com/ckwatson/ckwatson.git cd ckwatson uv sync

It's recommended (but not strictly necessary) to start a Redis server first: redis-server.

To run CKWatson, just run just run. The terminal should say:

[INFO] Listening at: http://127.0.0.1:8000 (30996)

Start playing by navigating to that URL.

The easiest way to run CKWatson, without even cloning this repo, is to hit this button and deploy to render.com:

Deploy to Render

Where's the Procfile? Back in 2016, I used Heroku for deploying CKWatson. When I looked again in mid-2025, but I had the easiest experience with Render (and they have a free tier), so I switched. This means the Procfile has been replaced with the render.yaml.

You can still self-host CKWatson. Read on.

You can either run CKWatson as a single container or with Redis using Docker Compose.

To run CKWatson as a single container:

  1. Build the image: docker build -t ckw .
  2. Start a container: docker run -p 80:80 --rm --name ckwatson ckw

To run CKWatson with Redis, simply use docker-compose up.

I will be using minikube in this walkthrough. I will be using the local Docker Registry as the source of the Kubernetes image.

Note: For production or remote clusters, push your image to a container registry and set imagePullPolicy: IfNotPresent or Always in the deployment YAML. The provided YAMLs now include resource requests/limits and health checks for better stability.

# Start the cluster: minikube start # Register the Docker Registry to minikube -- This is because we will be building the image from the Dockerfile for Kubernetes: eval $(minikube docker-env) # Build the Docker image for Kubernetes: docker build -t ckw . # Apply the Deployment and Service manifests: kubectl apply -f ./k8s # Access the web app: minikube service web
  • If you see ImagePullBackOff, ensure you ran eval $(minikube docker-env) before building.
  • For production, set up resource limits and health checks (already included in the YAMLs).
  • For Redis security in production, set a password and update the deployment and app config accordingly.

Here's the folder structure:

  • kernel does the chemistry.
  • puzzles stores definitions of puzzles. Admin can add puzzles to the game using the create page.
  • web powers the web app.

CKWatson follows the WSGI convention, a Python standard (PEP-3333) for building web servers. We achieve this by using the Flask framework.

Since a plotting job can take a while, we allow users to see status updates in the "messages" view of each job. These messages are streamed as server-sent events (SSEs) via the Flask-SSE extension.

Other significant extensions to Flask that CKWatson employs include:

  • Flask-Caching for caching computation results.
  • Flask-Limiter for rate-limiting. This is more of a security measure than it is a feature.
  • Flask-Compress for gzipping responses. This significantly reduces the bandwidth usage of our job results, which contains many SVG plots.

On the frontend side, CKWatson uses Bootstrap 5 for styling.

Read Entire Article