A self-hosted web app for tracking your video game collection — what you own, what you want, what you're playing, and how it's going — with Steam sync, wishlist sale alerts, and in-browser play for the games you own.
- Library tracking — owned games and a wishlist, per platform, region, and format (physical, digital, ISO, ROM, or Abandonware), with edition, storefront, steelbook, notes, and purchase or target price.
- IGDB-powered catalog — search IGDB, preview a game before adding it, or bulk-add several at once. Genres, companies, platforms, media, release dates, store links, collections, series, and addons (DLC, expansions, and packs) all come along.
- Personal tracking — progress, play sessions and a review per platform you own a game on, your own 1–10 star rating per game (shown beside IGDB's member and critic ratings), notes, and colored tags (with a Tag Manager and bulk tagging).
- Views, filters & sort — Covers, Table, or Overview views with an adjustable card size; filter by platform, format, storefront, tag, ownership, play status, game type, source, steelbook, collection, or series (each with an Exclude option), and sort by name or release date. Pages remember your search, filters, and sort.
- Hardware — devices and accessories from a curated Sony, Microsoft, Nintendo, and Sega catalog, with product photos.
- Steam sync — import your Steam library and wishlist with playtime, review every change before it's applied, and relink or unlink mismatched entries.
- Sale tracking — opt-in wishlist price tracking via IsThereAnyDeal (PC, Mac, Linux, and Android) and PlatPrices (PlayStation), with target prices and an On Sale page.
- Events — upcoming gaming-industry events from IGDB, with any featured games already in your library.
- In-browser play — upload ROMs for games you own and play over 25 systems right in the browser, with a self-hosted emulator and saves kept on your server. See docs/emulation.md.
- Media viewer — a lightbox for screenshots and artwork, and a video player for trailers.
- Overview & insights — headline numbers, what you're playing, recent additions, and gaps worth filling on the Overview; breakdowns by play status, platform, genre, and hardware on Insights; plus release calendars, duplicate detection, missing addons, orphaned accessories, and side-by-side game comparison.
- Share links — unlisted, read-only links to your Games or Hardware collection.
- Jobs — scheduled catalog resyncs, Steam import, sale refreshes, and event syncs, with live progress.
- Backup & restore — one JSON backup of your library, hardware, target prices and settings,
or a
.zipthat also carries your pick of ROMs and saves, BIOS files and uploaded images, with an automatic safety snapshot before every restore. - PWA — installable, works offline for anything you've already viewed, and syncs offline edits when you reconnect.
- Design — light, dark, and high-contrast modes with your choice of accent color (Material 3 color schemes), a sidebar that becomes a drawer on phones, and virtualized lists for large collections.
- Languages — English, Spanish, French, and Portuguese.
- Single admin, self-hosted — no public registration, no multi-tenancy.
The published Docker image bundles the frontend and backend into a single container. Create a
docker-compose.yml:
services:
app:
image: wwwescape/videogametrackarr:latest
container_name: videogametrackarr
ports:
- "8000:8000"
env_file:
- .env
volumes:
- db-data:/app/backend/db
- uploads-data:/app/backend/uploads
restart: unless-stopped
volumes:
db-data:
uploads-data:Create a .env file next to it (see Configuration), then start it:
docker compose up -dOpen http://localhost:8000. The first visit shows a create-admin form — fill it in once and
you're signed in. It asks for a one-time setup code, so nobody else who reaches the page first
can claim your instance: find it with docker compose logs app (or set your own with
SETUP_CODE in .env). Change your password later under Settings → General → Account. If
you ever get locked out,
docker compose exec app python -m scripts.create_admin --username admin resets the password.
Migrations run automatically on startup, and your database and uploads live in the named volumes, so they survive restarts and upgrades. Reverse proxy examples (Nginx, Traefik) are in docs/deployment/.
docker compose pull && docker compose up -dRunning from source instead? git pull, reinstall dependencies if they changed, then run
alembic upgrade head from backend/ before starting the app. Any breaking change is called
out in that release's notes.
Settings live in .env (see .env.example for every option). Only IGDB and a JWT
secret are required:
IGDB_CLIENT_ID=your_igdb_client_id
IGDB_CLIENT_SECRET=your_igdb_client_secret
JWT_SECRET_KEY= # generate with: python -c "import secrets; print(secrets.token_hex(32))"Get IGDB credentials at https://api-docs.igdb.com/#getting-started (free, requires a Twitch developer account).
Optional integrations — add a key to .env, then run docker compose up -d (a plain
docker compose restart doesn't pick up .env changes). Each shows a live status in
Settings → Integrations, along with the store region in use for the price integrations:
| Integration | Setting | Get a key | Notes |
|---|---|---|---|
| Steam | STEAM_API_KEY |
steamcommunity.com/dev/apikey | Your SteamID64 is set in-app, under Settings → Integrations. |
| IsThereAnyDeal | ITAD_API_KEY |
isthereanydeal.com/apps/my | PC, Mac, Linux, and Android prices. ITAD_COUNTRY (two-letter code, default US) sets the store country. |
| PlatPrices | PLATPRICES_API_KEY |
platprices.com/api-request | PlayStation prices. The free tier tracks any 2 PS Store regions, chosen on your PlatPrices dashboard. PLATPRICES_REGION (two-letter code such as GB or IN, default US) must be one of them. |
Other options: ROM_MAX_UPLOAD_MB (default 2048) caps ROM uploads — raise your reverse
proxy's upload limit to match. Behind a reverse proxy, set FORWARDED_ALLOW_IPS to the proxy's
address (or its Docker network, such as 172.16.0.0/12) so login rate limits count each visitor
rather than the proxy. DATABASE_URL (SQLite by default), REDIS_URL, and
CORS_ORIGINS are optional.
Requires Git, Node.js 22+, and Python 3.12+.
git clone https://github.com/wwwescape/VideoGameTrackarr.git
cd VideoGameTrackarr
npm install
cd backend
python -m venv .venv
.venv\Scripts\activate # Windows; use `source .venv/bin/activate` on macOS/Linux
pip install -r requirements-dev.txt
alembic upgrade headCreate .env in the project root as described in Configuration, then run the
backend and frontend in two terminals:
cd backend && .venv\Scripts\activate && uvicorn app.main:app --reload --port 8000npm startThe frontend runs on http://localhost:3000 and talks to the backend on http://localhost:8000.
npm run lint && npm run typecheck && npm test && npm run build
cd backend && ruff check . && pytestA Playwright end-to-end suite (npm run test:e2e) covers critical user journeys as a manual
pre-release check — see e2e/README.md.
git tag v1.26.0
git push origin v1.26.0The tag push publishes the Docker image to GHCR and Docker Hub (tagged with the version and
latest) and creates a GitHub Release. Publishing to Docker Hub needs the DOCKERHUB_USERNAME
and DOCKERHUB_TOKEN repository secrets.
frontend/ TypeScript, Vite, MUI, TanStack Query, React Router — own package.json
backend/ FastAPI, SQLAlchemy, Alembic (SQLite by default) — own requirements.txt
e2e/ Playwright end-to-end suite (manual pre-release check)
docs/ Developer guide, diagrams, emulation guide, and deployment examples
See docs/developer-guide.md for conventions, and CONTRIBUTING.md if you're sending a PR.
GPL-3.0 — see LICENSE.
If you find VideoGameTrackarr useful, consider buying me a coffee:




