A self-hosted typing speed trainer with sync across devices, leaderboards, and detailed per-key stats.
- Docker with the Compose plugin (v2.20+)
- Git
git clone https://github.com/luisced/typeflow
cd typeflowLinux / macOS
./deploy.sh --pull # prebuilt images from GHCR (recommended)
./deploy.sh # or build locally from this checkoutWindows (PowerShell)
.\deploy.ps1 -Pull # prebuilt images from GHCR (recommended)
.\deploy.ps1 # or build locally from this checkoutThe first run copies .env.example → .env and exits so you can fill in the required values. Edit the file and run the script again.
Prebuilt images are multi-arch (amd64 + arm64, so Raspberry Pi works) and published on every release: typeflow-api and typeflow-web. Pin a version with TYPEFLOW_VERSION=x.y.z in .env.
TypeFlow is up.
Frontend → http://localhost:3000
API → http://localhost:8000
All settings live in a single .env file at the project root. Required fields:
| Variable | Description |
|---|---|
POSTGRES_PASSWORD |
Database password |
TYPEFLOW_JWT_SECRET |
Random string ≥ 32 chars - generate with openssl rand -hex 32 |
TYPEFLOW_CORS_ORIGINS |
JSON array of allowed frontend origins |
Optional fields (commented out in .env.example - uncomment to override the default):
| Variable | Default | Description |
|---|---|---|
API_PORT |
8000 |
Host port for the API |
WEB_PORT |
3000 |
Host port for the frontend |
NEXT_PUBLIC_TYPEFLOW_API_URL |
http://localhost:8000 |
Public URL of the API as seen from the browser |
TYPEFLOW_REGISTRATION_OPEN |
true |
Set to false to close signups after your accounts are created |
TYPEFLOW_COOKIE_SECURE |
true |
Set to false only for local HTTP (no TLS) |
TYPEFLOW_ENV |
production |
Use development to allow weak JWT secrets |
- Set
NEXT_PUBLIC_TYPEFLOW_API_URL=https://api.yourdomain.comin.env - Set
TYPEFLOW_CORS_ORIGINS=["https://yourdomain.com"] - Set
TYPEFLOW_COOKIE_SECURE=true - Put a reverse proxy (Caddy, Nginx, Traefik) in front - the frontend runs on
WEB_PORTand the API onAPI_PORT - Run
./deploy.sh(or.\deploy.ps1)
./deploy.sh --pull # picks up the newest release imagesOr when building locally:
git pull
./deploy.shThe API container runs database migrations automatically on startup (alembic upgrade head), so no manual migration step is needed.
docker compose -f docker/docker-compose.yml --env-file .env downSee CONTRIBUTING.md.