Add CLAUDE.md documenting architecture and deploy pipeline
All checks were successful
Deploy / deploy (push) Successful in 39s
All checks were successful
Deploy / deploy (push) Successful in 39s
This commit is contained in:
parent
6bf6ed15d9
commit
e0e68bfba8
1 changed files with 81 additions and 0 deletions
81
CLAUDE.md
Normal file
81
CLAUDE.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# N64 Tracker
|
||||
|
||||
Flask app for tracking a personal N64 game collection: ownership status,
|
||||
loose cartridge prices (scraped from PriceCharting), rarity percentages
|
||||
(scraped from RarityGuide), and cover art (LaunchBox games DB, cached
|
||||
locally as WebP thumbnails). Runs as one Docker container on the user's
|
||||
Unraid home server.
|
||||
|
||||
## Architecture
|
||||
|
||||
- **`app.py`** — Flask routes for the game list/stats API, session-based
|
||||
password auth (single shared password, SHA-256 hashed in
|
||||
`/app/data/settings.json`), and three scrapers:
|
||||
- `scrape_pricecharting()` — loose cartridge prices, paginated via a
|
||||
cursor-based form POST loop.
|
||||
- `scrape_rarityguide()` — rarity % + label, fuzzy-matched to game titles
|
||||
via `difflib` (handles minor title spelling differences between
|
||||
sources).
|
||||
- `scrape_game_info()` — cover art + metadata from LaunchBox's games DB,
|
||||
only fetched lazily on first view/ownership toggle of a game, not
|
||||
upfront for the whole collection.
|
||||
- Thumbnails: `generate_thumbnails()` runs in a background thread at
|
||||
startup, converting `Coverart/*.png` to 300px-wide WebP in
|
||||
`/app/data/thumbs` — serving thumbnails instead of full PNGs is what
|
||||
keeps the game grid fast.
|
||||
- `BASE_PREFIX = '/n64'` — the app expects to run under this subpath
|
||||
behind a reverse proxy; all routes are prefixed with it.
|
||||
- **`static/`** — frontend (vanilla JS/HTML/CSS), served by Flask directly.
|
||||
- **`games.json`** at the repo root is a **seed/reference copy**, not the
|
||||
live database — the actual live data is `/app/data/games.json` on the
|
||||
bind-mounted `data/` volume (gitignored, server-only).
|
||||
- **`Coverart/`** — ~1,600 PNG cover art images (~1.6GB). Deliberately
|
||||
**excluded from git** (`.gitignore`) — this is static reference data
|
||||
that doesn't change, and 1.6GB in git history would make every clone of
|
||||
this repo download all of it. It lives only on the server; the deploy
|
||||
workflow explicitly excludes it from the rsync `--delete` so a deploy
|
||||
never wipes it (see below).
|
||||
|
||||
## Local development
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
python3 app.py
|
||||
```
|
||||
|
||||
Runs on port 5000. Needs `Coverart/` populated locally to see cover art
|
||||
(not in git — copy it from the server if working on cover-art-related
|
||||
features, or work without it since it degrades gracefully).
|
||||
|
||||
## Deployment
|
||||
|
||||
**Target:** Unraid server, container path `/mnt/user/appdata/n64-tracker`,
|
||||
built from `Dockerfile`/`docker-compose.yml` in this repo. Container name
|
||||
`n64-tracker-n64-tracker-1`, host port `8585` → container port `5000`.
|
||||
|
||||
**Deploy mechanism: Forgejo push-to-deploy**, same pattern as the other
|
||||
three projects on this box — see `card-grader`'s `CLAUDE.md` for the full
|
||||
pipeline mechanics. Push to `main` on the `forgejo` remote
|
||||
(`https://git.hippofam.com/ninja_hippo/n64-tracker.git`) triggers
|
||||
`.forgejo/workflows/deploy.yml`, which syncs into
|
||||
`/mnt/user/appdata/n64-tracker` (excluding `.git`, `.env`, `data/`, and
|
||||
**`Coverart/`** — that last exclusion is load-bearing, since `Coverart/`
|
||||
isn't tracked in git at all and a `--delete` sync without excluding it
|
||||
would wipe the images on every deploy) and runs `docker compose up -d --build`.
|
||||
|
||||
**Persistent state, never touched by deploys:** `data/` (games.json,
|
||||
settings.json, thumbnail cache) and `Coverart/` are both server-only.
|
||||
`.env` holds `ADMIN_PASSWORD`/`SECRET_KEY`.
|
||||
|
||||
**Migration notes (2026-08-25):**
|
||||
- This container originally used a Docker **named volume**
|
||||
(`n64-tracker_game-data`) instead of a bind mount, which meant Unraid's
|
||||
Appdata Backup plugin (only knows about `/mnt/user/appdata`) silently
|
||||
never backed up the live game database. Migrated to a bind mount
|
||||
(`./data:/app/data`) with existing data copied over and verified intact
|
||||
before the named volume was deleted.
|
||||
- `ADMIN_PASSWORD` and `SECRET_KEY` were previously hardcoded in plain text
|
||||
directly in `docker-compose.yml`, which would have landed in git history
|
||||
the moment this repo was created. Moved to a gitignored `.env` file
|
||||
referenced via `env_file: .env` before this repo was ever initialized —
|
||||
neither secret is in git history.
|
||||
Loading…
Add table
Add a link
Reference in a new issue