Pokémon game collection tracker (Node/Express + React + SQLite)
  • TypeScript 73.9%
  • CSS 20.8%
  • Dockerfile 2.7%
  • JavaScript 1.9%
  • HTML 0.7%
Find a file
Freydis Mende 0ce57f8446
All checks were successful
CI / Backend – install (push) Successful in 14s
CI / Frontend – install, lint & build (push) Successful in 14s
CI / Docker Compose – build images (push) Successful in 3s
CI / deploy (push) Successful in 1s
Exclude backend from Watchtower auto-updates
2026-08-15 15:37:23 +02:00
.forgejo/workflows Migrate frontend and backend to TypeScript, add zod request validation 2026-08-14 23:18:19 +02:00
backend Migrate frontend and backend to TypeScript, add zod request validation 2026-08-14 23:18:19 +02:00
frontend Migrate frontend and backend to TypeScript, add zod request validation 2026-08-14 23:18:19 +02:00
.dockerignore Rename client/server to frontend/backend, add /api/health + /api/version, harmonize CI 2026-08-14 10:21:46 +02:00
.env.example Migrate production to the shared Postgres database 2026-08-14 21:44:47 +02:00
.gitignore Make host port configurable via HOST_PORT env var 2026-08-02 16:48:56 +02:00
docker-compose.yml Exclude backend from Watchtower auto-updates 2026-08-15 15:37:23 +02:00
Dockerfile Migrate frontend and backend to TypeScript, add zod request validation 2026-08-14 23:18:19 +02:00
README.md Migrate production to the shared Postgres database 2026-08-14 21:44:47 +02:00

Pokémon Game Collection Tracker

Tracks your Pokémon core-series games: generation, edition, main console, other compatible consoles, release year, whether you own it, who plays it, and whether it's been completed.

Comes pre-seeded with every core-series game and remake through generation 9, and a fixed player list (Freydis, Romy, Milena) — edit backend/seedData.js before first run if you want to change either.

Local development

Requires Node.js 18+.

# terminal 1 - backend (API on :3000, also serves seed/db)
cd backend
npm install
npm run dev

# terminal 2 - frontend (dev server on :5173, proxies /api to :3000)
cd frontend
npm install
npm run dev

Open http://localhost:5173.

Production build (single process)

cd frontend && npm install && npm run build && cd ..
cd backend && npm install && npm start

Express serves the built React app and the API from the same port (3000 by default, override with PORT).

Deploy with Docker

docker compose up -d --build

This builds the frontend and bundles it with the backend into one image, and connects it to the pkmngames database on the shared Postgres stack (the pg-shared external network, host pg-shared-db). Set PKMNGAMES_DB_PASSWORD to the role's password (see below). The container always listens on 3000 internally — put it behind your own reverse proxy / firewall rules on the VPS, since there's no login built in.

Changing the host port

If 3000 is already taken on your server, set HOST_PORT to whatever's free instead of editing docker-compose.yml:

cp .env.example .env
# edit .env, e.g. HOST_PORT=3001
docker compose up -d --build

In Portainer, set HOST_PORT and PKMNGAMES_DB_PASSWORD under the stack's Environment variables instead of using a .env file.

API

Method Path Description
GET /api/health Health check ({"status":"ok","database":"connected"}, 503 if the DB check fails)
GET /api/version Git commit hash baked in at build time ({"version":"<hash>"}, "unknown" outside Docker)
GET /api/players List players
GET /api/games List games (with owned/completed/player assignments)
POST /api/games Create a game
PATCH /api/games/:id Update owned/completed/player assignments

Data

  • Uses Postgres when DATABASE_URL is set (always true when running via docker-compose.yml) and SQLite otherwise — e.g. running the backend directly for local development. The SQLite file lives at DATA_DIR/pokemon.db (./data/pokemon.db locally).
  • Seeding only runs when the games/players tables are empty, so your edits (owned/completed/players) are never overwritten on restart.

Migrating an existing deployment to German titles

If you already deployed before the UI was translated to German, your DB still has the old English edition names (Red, Blue, Sword, …) — a redeploy will not rename them, since seeding only runs on empty tables. Run this once against that deployment's volume to rename them in place (owned/completed/ player assignments are untouched):

docker exec -it <container-name> node migrate-de-titles.js

or locally, pointing at the volume's data directory:

cd backend && DATA_DIR=/path/to/pkmn-data node migrate-de-titles.js

Safe to run more than once — already-migrated rows simply won't match and are skipped.

CI/CD

.forgejo/workflows/ci.yml runs on every push to main and every PR:

  1. backend — installs backend deps (npm ci).
  2. frontend — installs frontend deps, lints (oxlint), and builds (npm run build).
  3. dockerdocker compose build, so a broken image build fails the workflow.
  4. deploy — only on pushes to main, after the above pass: POSTs to a webhook (secrets.DEPLOY_WEBHOOK_URL) so Portainer re-pulls this repo and rebuilds/redeploys the stack.

The deploy step needs the webhook URL set as a repo secret first (it's not committed anywhere):

tea actions secrets create --repo freydis/pkmn-games DEPLOY_WEBHOOK_URL "<your webhook url>"

or set it via the web UI: repo → Settings → Actions → Secrets.