Skip to content

Deployment

SpaceSquare640 edited this page Jul 11, 2026 · 2 revisions

Deployment

PokéTrack currently ships two build artifacts from CI: a Docker image (for the web app) and a Windows .exe (for the desktop app). There is no publicly-hosted instance — running the web app means running it yourself, locally or on infrastructure you control.

Docker (web app)

docker build -t poketrack .
docker run -p 5000:5000 poketrack
# -> http://localhost:5000/

The image (Dockerfile, python:3.12-slim base) installs requirements.txt, copies the repo in, and runs run_web.py, binding to 0.0.0.0:5000 inside the container via env vars:

Env var Purpose
POKETRACK_WEB_HOST overrides config.json's web.host (set to 0.0.0.0 in the image)
POKETRACK_WEB_PORT overrides config.json's web.port

Env vars take precedence over config.json, so you can override host/port at docker run time without editing the config.

Persistence: the container's data/ (SQLite DB, image cache) and config.json live inside the container filesystem by default and are lost on container removal. Mount volumes if you want them to survive:

docker run -p 5000:5000 \
  -v poketrack-data:/app/data \
  -v $(pwd)/config.json:/app/config.json \
  poketrack

The Rust native fast path is not built into the Docker image — the image installs from requirements.txt only, so the web app runs on the pure-Python path inside the container. This is intentional: it keeps the image build simple and dependency-free (no Rust toolchain in the image), and the fallback is designed to be just as correct, only somewhat slower to parse. Build a custom image on top if you want the native path included (pip install maturin && pip install ./poketrack-native as an extra layer).

Windows executable (desktop app)

pip install pyinstaller
pyinstaller --noconfirm PokeTrack.spec
# -> dist/PokeTrack.exe

PokeTrack.spec bundles languages.json, data/regions_map.json, the CustomTkinter theme files, and — if installed at build time — the poketrack_native extension and the app icon (assets/icon.ico). It's a one-file, windowed (no console) build.

At runtime, the frozen exe reads bundled read-only assets from a temp extraction dir (sys._MEIPASS, exposed as RESOURCE_ROOT), while writable files (config.json, the SQLite DB, image cache) live next to the executable (ROOT) — see poketrack/app_context.py.

CI

Two workflows under .github/workflows/:

  • ci.yml — runs on every push. Three jobs:
    • test — pytest matrix across Python 3.11–3.13, no Rust toolchain (proves the pure-Python fallback path works standalone).
    • native — builds the Rust extension (via maturin) on Python 3.12 and runs the full suite with it installed, so the native/Python parity test actually exercises both code paths.
    • frontend — type-checks and builds the TypeScript bundle (npm ci && npm run build).
  • release.yml — triggered by publishing a GitHub Release. Builds the Rust wheel, installs it (so PyInstaller bundles the fast path), builds PokeTrack.exe via PokeTrack.spec, and attaches both PokeTrack.exe and the native wheel to the release. Source code zip/tarball are attached automatically by GitHub.

Release process

  1. Bump poketrack/__init__.py's __version__.
  2. Add a CHANGELOG.md entry.
  3. Commit, push to main.
  4. Tag: git tag -a vX.Y.Z -m "..." then git push origin vX.Y.Z.
  5. Publish a GitHub Release against that tag (via the web UI, or gh release create vX.Y.Z --notes "...") — this triggers release.yml automatically, which attaches the .exe and wheel within a few minutes.

Hosting the web app publicly

Not currently set up. If you want a public URL, the web app is a plain Flask app with a Dockerfile already in place, so any container-friendly host (Render, Fly.io, Railway, a VPS, etc.) works with minimal extra configuration — the main things to plan for:

  • Persistent storage for data/poketrack.db and config.json (a volume, or point database_path at a managed disk).
  • Secrets: don't bake webhook_url/webhook_secret/Telegram tokens into the image — inject them via the platform's env/secret mechanism and read them into config.json at startup, or extend Config to read overrides from env vars.
  • Single-user assumption: there's no auth layer (see Web API) — put the deployment behind your own auth/reverse proxy if it needs to be restricted.
  • Background scheduler: service.start() runs APScheduler in-process; make sure your host doesn't scale the web process to multiple replicas without addressing that (it would fetch/notify multiple times per interval).

See Architecture for how the service/database/scheduler are wired together if you're adapting this for a specific platform.

Clone this wiki locally