Compare commits
15 Commits
6a86c56e3b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd267499b8 | ||
|
|
3254103cf6 | ||
|
|
6f4ed3460b | ||
|
|
fae6532b8a | ||
|
|
31355975e1 | ||
|
|
83a17c8f15 | ||
|
|
7ea6b30396 | ||
|
|
3f39b5f0cb | ||
| 61a7f57f1f | |||
| 03f07ebee5 | |||
| 972137acfb | |||
| fd23d89e71 | |||
| d9d547ef53 | |||
| 349a0cb821 | |||
| ad4ac6cf8c |
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-0arz
|
||||||
|
title: Integration tests for Runs & Encounters API
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:21Z
|
||||||
|
updated_at: 2026-02-10T09:33:21Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write integration tests for the core run tracking and encounter API endpoints. This is the heart of the application.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test run CRUD operations (create, list, get, update, delete)
|
||||||
|
- [ ] Test run creation with rules configuration (JSONB field)
|
||||||
|
- [ ] Test encounter logging on a run (create encounter on a route)
|
||||||
|
- [ ] Test encounter status changes (alive → dead, alive → retired, etc.)
|
||||||
|
- [ ] Test duplicate encounter prevention (dupes clause logic)
|
||||||
|
- [ ] Test shiny encounter handling
|
||||||
|
- [ ] Test egg encounter handling
|
||||||
|
- [ ] Test ending a run (completion/failure)
|
||||||
|
- [ ] Test error cases (encounter on invalid route, duplicate route encounters, etc.)
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Run endpoints: `backend/src/app/api/runs.py`
|
||||||
|
- Encounter endpoints: `backend/src/app/api/encounters.py`
|
||||||
|
- This is the most critical area — Nuzlocke rules enforcement should be thoroughly tested
|
||||||
|
- Tests need game + pokemon + route fixtures as prerequisites
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-1e9k
|
||||||
|
title: Populate encounter data for Gen 8+ stub games
|
||||||
|
status: todo
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T08:59:02Z
|
||||||
|
updated_at: 2026-02-10T08:59:02Z
|
||||||
|
parent: nuzlocke-tracker-rzu4
|
||||||
|
---
|
||||||
|
|
||||||
|
Fill in encounter data for games that currently have null/stub seed files. These games are not covered by PokeAPI and require manual curation or an alternative data source.
|
||||||
|
|
||||||
|
## Games with null/stub data:
|
||||||
|
- [ ] Sword (null)
|
||||||
|
- [ ] Shield (null)
|
||||||
|
- [ ] Brilliant Diamond (null)
|
||||||
|
- [ ] Shining Pearl (null)
|
||||||
|
- [ ] Scarlet (null)
|
||||||
|
- [ ] Violet (null)
|
||||||
|
- [ ] Legends Arceus (null)
|
||||||
|
|
||||||
|
## Format requirements:
|
||||||
|
Each game's JSON file must follow the existing structure:
|
||||||
|
\`\`\`json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Route Name",
|
||||||
|
"order": 1,
|
||||||
|
"encounters": [
|
||||||
|
{
|
||||||
|
"pokeapi_id": 25,
|
||||||
|
"pokemon_name": "pikachu",
|
||||||
|
"method": "walk",
|
||||||
|
"encounter_rate": 10,
|
||||||
|
"min_level": 5,
|
||||||
|
"max_level": 8
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Notes:
|
||||||
|
- This is likely the largest manual task unless the "explore automated sources" task finds a viable alternative
|
||||||
|
- Depends on findings from the automated data sources task — if automation is viable, this becomes much easier
|
||||||
|
- Sword/Shield and Scarlet/Violet use open-world/Wild Area mechanics that may need special handling
|
||||||
|
- Legends Arceus has a fundamentally different encounter system (overworld encounters, alpha Pokémon, space-time distortions)
|
||||||
|
- BD/SP are remakes of Diamond/Pearl — existing D/P data could serve as a starting point
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-1guz
|
||||||
|
title: Component tests for key frontend components
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:45Z
|
||||||
|
updated_at: 2026-02-10T09:33:45Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write component tests for the most important frontend React components, focusing on user interactions and rendering correctness.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test `EncounterModal` — form submission, validation, Pokemon selection
|
||||||
|
- [ ] Test `StatusChangeModal` — status transitions, confirmation flow
|
||||||
|
- [ ] Test `EndRunModal` — run completion/failure flow
|
||||||
|
- [ ] Test `GameGrid` — game selection rendering, click handling
|
||||||
|
- [ ] Test `RulesConfiguration` — rules toggle interactions, state management
|
||||||
|
- [ ] Test `Layout` — navigation rendering, responsive behavior
|
||||||
|
- [ ] Test admin form modals (GameFormModal, RouteFormModal, PokemonFormModal) — CRUD form flows
|
||||||
|
- [ ] Test `AdminTable` — sorting, filtering, action buttons
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Focus on user-facing behavior, not implementation details
|
||||||
|
- Use @testing-library/user-event for simulating clicks, typing, etc.
|
||||||
|
- Mock API responses for components that fetch data
|
||||||
|
- Don't aim for 100% coverage — prioritise the most complex/interactive components
|
||||||
|
- Page components (RunEncounters, RunDashboard, etc.) are large and complex — consider testing their sub-components instead
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-2b4r
|
||||||
|
title: Add route ordering for Gen 5+ games
|
||||||
|
status: todo
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T08:58:55Z
|
||||||
|
updated_at: 2026-02-10T08:58:55Z
|
||||||
|
parent: nuzlocke-tracker-rzu4
|
||||||
|
---
|
||||||
|
|
||||||
|
Add route progression ordering in `route_order.json` for all games that currently lack it. Routes should be ordered to match the typical in-game progression (main story first, post-game after).
|
||||||
|
|
||||||
|
## Games needing route ordering:
|
||||||
|
- [ ] Diamond/Pearl (could alias to Platinum if progression is similar enough)
|
||||||
|
- [ ] Black/White
|
||||||
|
- [ ] Black 2/White 2
|
||||||
|
- [ ] X/Y
|
||||||
|
- [ ] Sun/Moon
|
||||||
|
- [ ] Ultra Sun/Ultra Moon (could alias to Sun/Moon if similar enough)
|
||||||
|
- [ ] Sword/Shield
|
||||||
|
- [ ] Brilliant Diamond/Shining Pearl (could alias to Platinum/Diamond-Pearl)
|
||||||
|
- [ ] Scarlet/Violet
|
||||||
|
- [ ] Legends Arceus
|
||||||
|
- [ ] Legends Z-A
|
||||||
|
- [ ] Let's Go Pikachu/Eevee (currently aliased to firered-leafgreen — verify this is correct)
|
||||||
|
|
||||||
|
## Approach:
|
||||||
|
- Reference Bulbapedia "walkthrough" or "appendix" pages for progression order
|
||||||
|
- Consider aliasing games that share the same region and route progression
|
||||||
|
- Mark a clear divider between main story and post-game routes where applicable
|
||||||
|
- The format is an array of route name strings in `route_order.json`, keyed by version group slug
|
||||||
|
|
||||||
|
## Notes:
|
||||||
|
- This is primarily manual work — play order guides are widely available online
|
||||||
|
- Verify route names match exactly what's in the encounter data files (case-sensitive)
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-3lfw
|
# nuzlocke-tracker-3lfw
|
||||||
title: Configure Nginx Proxy Manager for nuzlocke-tracker
|
title: Configure Nginx Proxy Manager for nuzlocke-tracker
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
priority: normal
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:50Z
|
created_at: 2026-02-09T15:30:50Z
|
||||||
updated_at: 2026-02-09T15:31:15Z
|
updated_at: 2026-02-10T08:44:18Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
blocking:
|
blocking:
|
||||||
- nuzlocke-tracker-vpn5
|
- nuzlocke-tracker-vpn5
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-6lud
|
||||||
|
title: Audit and fix route ordering for Gen 1-4 games
|
||||||
|
status: todo
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T08:59:16Z
|
||||||
|
updated_at: 2026-02-10T08:59:16Z
|
||||||
|
parent: nuzlocke-tracker-rzu4
|
||||||
|
---
|
||||||
|
|
||||||
|
Review the existing route ordering for Gen 1-4 games that already have ordering defined. The current ordering may not accurately reflect typical game progression.
|
||||||
|
|
||||||
|
## Games to audit:
|
||||||
|
- [ ] FireRed/LeafGreen (and aliased: Red/Blue, Yellow, Let's Go)
|
||||||
|
- [ ] HeartGold/SoulSilver (and aliased: Gold/Silver, Crystal)
|
||||||
|
- [ ] Emerald (and aliased: Ruby/Sapphire, Omega Ruby/Alpha Sapphire)
|
||||||
|
- [ ] Platinum
|
||||||
|
|
||||||
|
## What to check:
|
||||||
|
- Routes are in correct progression order (match typical walkthrough)
|
||||||
|
- No routes are missing from the ordering
|
||||||
|
- No routes are listed that don't exist in the encounter data
|
||||||
|
- Aliases make sense (e.g. Red/Blue may have slightly different progression from FR/LG)
|
||||||
|
- Post-game areas are placed after main story areas
|
||||||
|
- Sub-areas (children) inherit parent ordering correctly
|
||||||
|
|
||||||
|
## Notes:
|
||||||
|
- Cross-reference with Bulbapedia walkthrough pages
|
||||||
|
- The Platinum ordering currently starts with cities and mines rather than the starting town/routes — this may be incorrect
|
||||||
|
- Diamond/Pearl currently aliases to nothing — check if it should alias to Platinum or needs its own ordering
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-7jba
|
||||||
|
title: Review and complete special encounters for all games
|
||||||
|
status: todo
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T08:59:24Z
|
||||||
|
updated_at: 2026-02-10T08:59:24Z
|
||||||
|
parent: nuzlocke-tracker-rzu4
|
||||||
|
---
|
||||||
|
|
||||||
|
Audit \`special_encounters.json\` to ensure starters, gifts, fossils, and other non-wild encounters are covered for all games.
|
||||||
|
|
||||||
|
## What counts as special encounters:
|
||||||
|
- **Starters** — the three (or more) starter Pokémon choices
|
||||||
|
- **Gift Pokémon** — NPCs that give you Pokémon (e.g. Eevee in Celadon, Lapras in Silph Co.)
|
||||||
|
- **Fossils** — Pokémon revived from fossils (e.g. Omanyte/Kabuto, Lileep/Anorith)
|
||||||
|
- **In-game trades** — Pokémon received via NPC trades (if tracked)
|
||||||
|
- **Static encounters** — Legendaries, Snorlax blocking the road, Sudowoodo, etc.
|
||||||
|
- **Event-specific** — One-time encounters tied to story events
|
||||||
|
|
||||||
|
## Checklist:
|
||||||
|
- [ ] Audit Gen 1 (Red/Blue/Yellow/FR/LG) special encounters
|
||||||
|
- [ ] Audit Gen 2 (Gold/Silver/Crystal/HG/SS) special encounters
|
||||||
|
- [ ] Audit Gen 3 (Ruby/Sapphire/Emerald/ORAS) special encounters
|
||||||
|
- [ ] Audit Gen 4 (Diamond/Pearl/Platinum/BD/SP) special encounters
|
||||||
|
- [ ] Audit Gen 5 (Black/White/B2/W2) special encounters
|
||||||
|
- [ ] Audit Gen 6 (X/Y) special encounters
|
||||||
|
- [ ] Audit Gen 7 (Sun/Moon/USUM) special encounters
|
||||||
|
- [ ] Audit Gen 8+ (Sword/Shield/Scarlet/Violet/Legends) special encounters
|
||||||
|
|
||||||
|
## Notes:
|
||||||
|
- Cross-reference with Bulbapedia "Gift Pokémon" and "In-game trade" pages
|
||||||
|
- The current file appears focused on Gen 1-2 — later gens likely need additions
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-9c66
|
||||||
|
title: Integration tests for Genlockes & Bosses API
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:26Z
|
||||||
|
updated_at: 2026-02-10T09:33:26Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write integration tests for the genlocke challenge and boss battle API endpoints.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test genlocke CRUD operations (create, list, get, update, delete)
|
||||||
|
- [ ] Test leg management (add/remove legs to a genlocke)
|
||||||
|
- [ ] Test Pokemon transfers between genlocke legs
|
||||||
|
- [ ] Test boss battle CRUD (create, list, update, delete per game)
|
||||||
|
- [ ] Test boss battle results per run (record win/loss)
|
||||||
|
- [ ] Test stats endpoint for run statistics
|
||||||
|
- [ ] Test export endpoint
|
||||||
|
- [ ] Test error cases (invalid transfers, boss results for wrong game, etc.)
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Genlocke endpoints: `backend/src/app/api/genlockes.py`
|
||||||
|
- Boss endpoints: `backend/src/app/api/bosses.py`
|
||||||
|
- Stats endpoints: `backend/src/app/api/stats.py`
|
||||||
|
- Export endpoints: `backend/src/app/api/export.py`
|
||||||
|
- Genlocke tests require multiple runs as fixtures
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-ahza
|
# nuzlocke-tracker-ahza
|
||||||
title: Deployment Strategy
|
title: Deployment Strategy
|
||||||
status: todo
|
status: in-progress
|
||||||
type: epic
|
type: epic
|
||||||
priority: normal
|
priority: normal
|
||||||
created_at: 2026-02-09T14:03:53Z
|
created_at: 2026-02-09T14:03:53Z
|
||||||
updated_at: 2026-02-09T15:08:29Z
|
updated_at: 2026-02-10T08:16:36Z
|
||||||
---
|
---
|
||||||
|
|
||||||
Define and implement a deployment strategy for running the nuzlocke-tracker in production on a local Unraid server while keeping laptop/PC as the development environment.
|
Define and implement a deployment strategy for running the nuzlocke-tracker in production on a local Unraid server while keeping laptop/PC as the development environment.
|
||||||
@@ -16,19 +16,18 @@ Define and implement a deployment strategy for running the nuzlocke-tracker in p
|
|||||||
- **Dev environment:** Laptop/PC — continue using the existing `docker-compose.yml` for local development
|
- **Dev environment:** Laptop/PC — continue using the existing `docker-compose.yml` for local development
|
||||||
- **Production host:** Unraid server running Docker containers
|
- **Production host:** Unraid server running Docker containers
|
||||||
- **Networking:** LAN-only access, Nginx Proxy Manager already in place on Unraid
|
- **Networking:** LAN-only access, Nginx Proxy Manager already in place on Unraid
|
||||||
- **Orchestration:** Docker Compose for production (matching dev workflow). Install Portainer for container management and semi-automated deployments.
|
- **Orchestration:** Docker Compose for production (matching dev workflow). Deploy via SSH from the dev machine.
|
||||||
|
|
||||||
## Decided Approach
|
## Decided Approach
|
||||||
|
|
||||||
**Docker Compose + Portainer + Local Docker Registry**
|
**Docker Compose + SSH + Gitea (source hosting, container registry)**
|
||||||
|
|
||||||
1. **A local Docker registry** runs on Unraid as a container, accessible on the LAN (e.g., `unraid:5000` or behind Nginx Proxy Manager).
|
1. **Gitea** runs on Unraid behind Nginx Proxy Manager with SSL (e.g., `gitea.nerdboden.de`). It serves as the self-hosted Git remote and container registry.
|
||||||
2. **Images are built on the dev machine** and pushed to the local registry.
|
2. **Images are built on the dev machine** (podman or docker, cross-compiled for linux/amd64) and pushed to Gitea's container registry as **user-level packages** (e.g., `gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest`, `gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest`).
|
||||||
3. **Production runs docker-compose** on Unraid, pulling images from the local registry instead of mounting source.
|
3. **Production runs docker compose** on Unraid at `/mnt/user/appdata/nuzlocke-tracker/`, pulling images from the Gitea container registry instead of mounting source.
|
||||||
4. **Portainer** is installed on Unraid to manage stacks, provide a web UI, and enable webhook-triggered redeployments.
|
4. **A deploy script** on the dev machine automates the full flow: build images → push to Gitea registry → SCP compose file to Unraid → generate `.env` if missing → SSH to pull images and (re)start containers.
|
||||||
5. **A deploy script** on the dev machine automates the full flow: build images → push to local registry → trigger Portainer webhook to redeploy.
|
5. **Nginx Proxy Manager** handles routing on the LAN (e.g., `nuzlocke.nerdboden.de` → frontend container, `gitea.nerdboden.de` → Gitea).
|
||||||
6. **Nginx Proxy Manager** handles routing on the LAN (e.g., `nuzlocke.local` → frontend container).
|
6. **Database** uses a bind mount (`./data/postgres`) for persistence on the Unraid disk; migrations run automatically on API container startup.
|
||||||
7. **Database** uses a named Docker volume for persistence; migrations run automatically on API container startup.
|
|
||||||
|
|
||||||
## Branching Strategy
|
## Branching Strategy
|
||||||
|
|
||||||
@@ -42,19 +41,18 @@ Define and implement a deployment strategy for running the nuzlocke-tracker in p
|
|||||||
1. Create `feature/xyz` from `develop`
|
1. Create `feature/xyz` from `develop`
|
||||||
2. Work on the feature, commit, merge into `develop`
|
2. Work on the feature, commit, merge into `develop`
|
||||||
3. When ready to deploy: merge `develop` → `main`
|
3. When ready to deploy: merge `develop` → `main`
|
||||||
4. Run `./deploy.sh` (builds from `main`, pushes to local registry, triggers Portainer webhook)
|
4. Run `./deploy.sh` (builds from `main`, pushes to Gitea registry, deploys to Unraid via SSH)
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
|
|
||||||
- [ ] **Set up branching structure** — create `develop` branch from `main`, establish the `main`/`develop`/`feature/*` workflow
|
- [ ] **Set up branching structure** — create `develop` branch from `main`, establish the `main`/`develop`/`feature/*` workflow
|
||||||
- [ ] **Update CLAUDE.md with branching rules** — once the branching structure is in place, add instructions to CLAUDE.md that the branching strategy must be adhered to (always work on feature branches, never commit directly to `main`, merge flow is `feature/*` → `develop` → `main`)
|
- [ ] **Update CLAUDE.md with branching rules** — once the branching structure is in place, add instructions to CLAUDE.md that the branching strategy must be adhered to (always work on feature branches, never commit directly to `main`, merge flow is `feature/*` → `develop` → `main`)
|
||||||
- [ ] **Set up local Docker registry on Unraid** — run the `registry:2` container, configure storage volume, optionally put it behind Nginx Proxy Manager with a hostname (e.g., `registry.local`)
|
- [ ] **Configure Gitea container registry** — create an access token with `read:package` and `write:package` scopes, verify `docker login gitea.nerdboden.de` works, test pushing and pulling an image as a user-level package
|
||||||
- [ ] **Create production docker-compose file** (`docker-compose.prod.yml`) — uses images from the local registry, production env vars, no source volume mounts, proper restart policies
|
- [x] **Create production docker-compose file** (`docker-compose.prod.yml`) — uses images from the Gitea container registry, production env vars, no source volume mounts, proper restart policies
|
||||||
- [ ] **Create production Dockerfiles (or multi-stage builds)** — ensure frontend is built and served statically (e.g., via the API or a lightweight nginx container), API runs without debug mode
|
- [x] **Create production Dockerfiles (or multi-stage builds)** — ensure frontend is built and served statically (e.g., via the API or a lightweight nginx container), API runs without debug mode
|
||||||
- [ ] **Set up Portainer on Unraid** — install Portainer CE as a Docker container, configure the stack from the production compose file
|
- [x] **Create deploy script** — `./deploy.sh` builds images (podman/docker, linux/amd64), pushes to Gitea registry, SCPs compose file, generates `.env` if needed, pulls and starts containers via SSH
|
||||||
- [ ] **Configure Portainer webhook for automated redeployment** — add a webhook trigger in Portainer that pulls latest images and restarts the stack
|
- [x] **Configure Nginx Proxy Manager** — add proxy host entries for Gitea and the nuzlocke-tracker frontend/API on the appropriate ports
|
||||||
- [ ] **Create deploy script** — a script (e.g., `./deploy.sh`) that builds images from `main`, tags them for the local registry, pushes them, and triggers the Portainer webhook to redeploy
|
- [x] **Environment & secrets management** — deploy script auto-generates `.env` with `POSTGRES_PASSWORD` on Unraid if missing; file lives at `/mnt/user/appdata/nuzlocke-tracker/.env`
|
||||||
- [ ] **Configure Nginx Proxy Manager** — add proxy host entry pointing to the frontend/API containers on the appropriate ports
|
- [ ] **Implement Gitea Actions CI/CD pipeline** — set up Gitea Actions runner on Unraid, create CI workflow (lint/test on `develop`) and deploy workflow (build/push/deploy on `main`); uses GitHub Actions-compatible syntax for portability
|
||||||
- [ ] **Environment & secrets management** — create a `.env.prod` template, document required variables, decide on secret handling (`.env` file on Unraid, Portainer env vars, etc.)
|
- [ ] **Database backup strategy** — set up a simple scheduled backup for the PostgreSQL data (e.g., cron + `pg_dump` script on Unraid)
|
||||||
- [ ] **Database backup strategy** — set up a simple scheduled backup for the PostgreSQL volume/data (e.g., cron + `pg_dump` script on Unraid)
|
|
||||||
- [ ] **Document the deployment workflow** — README or docs covering how to deploy, redeploy, rollback, and manage the production instance
|
- [ ] **Document the deployment workflow** — README or docs covering how to deploy, redeploy, rollback, and manage the production instance
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-aiw6
|
# nuzlocke-tracker-aiw6
|
||||||
title: Create deploy script
|
title: Create deploy script
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
priority: normal
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:48Z
|
created_at: 2026-02-09T15:30:48Z
|
||||||
updated_at: 2026-02-09T15:31:15Z
|
updated_at: 2026-02-09T17:28:22Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
blocking:
|
blocking:
|
||||||
- nuzlocke-tracker-izf6
|
- nuzlocke-tracker-izf6
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-ch77
|
||||||
|
title: Integration tests for Games & Routes API
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:13Z
|
||||||
|
updated_at: 2026-02-10T09:33:13Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write integration tests for the games and routes API endpoints in `backend/src/app/api/games.py`.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test CRUD operations for games (create, list, get, update, delete)
|
||||||
|
- [ ] Test route management within a game (create, list, reorder, update, delete)
|
||||||
|
- [ ] Test route encounter management (add/remove Pokemon to routes)
|
||||||
|
- [ ] Test bulk import functionality
|
||||||
|
- [ ] Test region grouping/filtering
|
||||||
|
- [ ] Test error cases (404 for missing games, validation errors, duplicate handling)
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Use the httpx AsyncClient fixture from the test infrastructure task
|
||||||
|
- Each test should be independent — use fixtures to set up required data
|
||||||
|
- Test both success and error response codes and bodies
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-d8cp
|
||||||
|
title: Set up frontend test infrastructure
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
priority: normal
|
||||||
|
created_at: 2026-02-10T09:33:33Z
|
||||||
|
updated_at: 2026-02-10T09:34:00Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
blocking:
|
||||||
|
- nuzlocke-tracker-ee9s
|
||||||
|
- nuzlocke-tracker-1guz
|
||||||
|
---
|
||||||
|
|
||||||
|
Set up the test infrastructure for the React/TypeScript frontend. No testing tooling currently exists.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Install Vitest, @testing-library/react, @testing-library/jest-dom, @testing-library/user-event, jsdom
|
||||||
|
- [ ] Configure Vitest in `vite.config.ts` or a dedicated `vitest.config.ts`
|
||||||
|
- [ ] Set up jsdom as the test environment
|
||||||
|
- [ ] Create a test setup file (e.g. `src/test/setup.ts`) that imports @testing-library/jest-dom matchers
|
||||||
|
- [ ] Create test utility helpers (e.g. render wrapper with providers — QueryClientProvider, BrowserRouter)
|
||||||
|
- [ ] Add a \`test\` script to package.json
|
||||||
|
- [ ] Verify the setup by writing a simple smoke test
|
||||||
|
- [ ] Set up MSW (Mock Service Worker) or a similar API mocking strategy for hook/component tests
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Vitest integrates natively with Vite, which the project already uses
|
||||||
|
- React Testing Library is the standard for testing React components
|
||||||
|
- The app uses React Query (TanStack Query) and React Router — the test wrapper needs to provide these contexts
|
||||||
|
- MSW is recommended for mocking API calls in hook and component tests, but simpler approaches (vi.mock) may suffice initially
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-ee9s
|
||||||
|
title: Unit tests for frontend utilities and hooks
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:38Z
|
||||||
|
updated_at: 2026-02-10T09:33:38Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write unit tests for the frontend utility functions and custom React hooks.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test `utils/formatEvolution.ts` — evolution chain formatting logic
|
||||||
|
- [ ] Test `utils/download.ts` — file download utility
|
||||||
|
- [ ] Test `hooks/useRuns.ts` — run CRUD hook with mocked API
|
||||||
|
- [ ] Test `hooks/useGames.ts` — game fetching hook
|
||||||
|
- [ ] Test `hooks/useEncounters.ts` — encounter operations hook
|
||||||
|
- [ ] Test `hooks/usePokemon.ts` — pokemon data hook
|
||||||
|
- [ ] Test `hooks/useGenlockes.ts` — genlocke operations hook
|
||||||
|
- [ ] Test `hooks/useBosses.ts` — boss operations hook
|
||||||
|
- [ ] Test `hooks/useStats.ts` — stats fetching hook
|
||||||
|
- [ ] Test `hooks/useAdmin.ts` — admin operations hook
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Utility functions are pure functions — straightforward to test
|
||||||
|
- Hooks wrap React Query — test that they call the right API endpoints, handle loading/error states, and invalidate queries correctly
|
||||||
|
- Use `@testing-library/react`'s `renderHook` for hook testing
|
||||||
|
- Mock the API client (from `src/api/`) rather than individual fetch calls
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-hjkk
|
||||||
|
title: Unit tests for Pydantic schemas and model validation
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:03Z
|
||||||
|
updated_at: 2026-02-10T09:33:03Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write unit tests for the Pydantic schemas in `backend/src/app/schemas/`. These are pure validation logic and can be tested without a database.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test `CamelModel` base class (snake_case → camelCase alias generation)
|
||||||
|
- [ ] Test run schemas — creation validation, required fields, optional fields, serialization
|
||||||
|
- [ ] Test game schemas — validation rules, field constraints
|
||||||
|
- [ ] Test encounter schemas — status enum validation, field dependencies
|
||||||
|
- [ ] Test boss schemas — nested model validation
|
||||||
|
- [ ] Test genlocke schemas — complex nested structures
|
||||||
|
- [ ] Test stats schemas — response model structure
|
||||||
|
- [ ] Test evolution schemas — validation of evolution chain data
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Focus on: valid input acceptance, invalid input rejection, serialization output format
|
||||||
|
- The `CamelModel` base class does alias generation — verify both input (camelCase) and output (camelCase) work
|
||||||
|
- Test edge cases like empty strings, negative numbers, missing required fields
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-hwyk
|
# nuzlocke-tracker-hwyk
|
||||||
title: Set up Portainer on Unraid
|
title: Set up Portainer on Unraid
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:44Z
|
created_at: 2026-02-09T15:30:44Z
|
||||||
updated_at: 2026-02-09T15:30:44Z
|
updated_at: 2026-02-09T16:53:41Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-iam7
|
||||||
|
title: Unit tests for services layer
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:08Z
|
||||||
|
updated_at: 2026-02-10T09:33:08Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write unit tests for the business logic in `backend/src/app/services/`. Currently this is the `families.py` service which handles Pokemon evolution family resolution.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test family resolution with simple linear evolution chains (e.g. A → B → C)
|
||||||
|
- [ ] Test family resolution with branching evolutions (e.g. Eevee)
|
||||||
|
- [ ] Test family resolution with region-specific evolutions
|
||||||
|
- [ ] Test edge cases: single-stage Pokemon, circular references (if possible), missing data
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- `services/families.py` contains the core logic for resolving Pokemon evolution families
|
||||||
|
- These tests may need mock database sessions or in-memory data depending on how the service queries data
|
||||||
|
- If the service methods take a DB session, mock it; if they operate on data objects, pass test data directly
|
||||||
@@ -1,16 +1,20 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-izf6
|
# nuzlocke-tracker-izf6
|
||||||
title: Set up local Docker registry on Unraid
|
title: Configure Gitea container registry
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:40Z
|
created_at: 2026-02-09T15:30:40Z
|
||||||
updated_at: 2026-02-09T15:30:40Z
|
updated_at: 2026-02-09T16:53:09Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
---
|
---
|
||||||
|
|
||||||
Run a `registry:2` container on the Unraid server for storing production Docker images locally.
|
Set up and verify the Gitea container registry for hosting Docker images as user-level packages.
|
||||||
|
|
||||||
- Run `registry:2` as a Docker container on Unraid
|
## Checklist
|
||||||
- Configure a persistent storage volume for the registry data
|
|
||||||
- Optionally put it behind Nginx Proxy Manager with a hostname (e.g., `registry.local`)
|
- [ ] Create a Gitea access token with `read:package` and `write:package` scopes
|
||||||
- Verify pushing/pulling images from the dev machine works
|
- [ ] Verify `docker login gitea.nerdboden.de` works from the dev machine
|
||||||
|
- [ ] Test pushing a Docker image as a user-level package (e.g., `gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest`)
|
||||||
|
- [ ] Verify the image appears under the user's Packages tab in Gitea
|
||||||
|
- [ ] Test pulling the image back (from Unraid or dev machine)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-jlzs
|
||||||
|
title: Implement Gitea Actions CI/CD pipeline
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:38:15Z
|
||||||
|
updated_at: 2026-02-10T09:38:15Z
|
||||||
|
parent: nuzlocke-tracker-ahza
|
||||||
|
---
|
||||||
|
|
||||||
|
Set up Gitea Actions as the CI/CD pipeline for the nuzlocke-tracker. Gitea Actions uses the same syntax as GitHub Actions, making it portable if the project goes public on GitHub later.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
- Gitea is already running on Unraid behind Nginx Proxy Manager (`gitea.nerdboden.de`)
|
||||||
|
- Images are currently built locally and pushed to the Gitea container registry via `deploy.sh`
|
||||||
|
- Gitea Actions can automate building, pushing images, and triggering deployment on push to `main`
|
||||||
|
- The workflow syntax is compatible with GitHub Actions, so the same `.github/workflows/` files work on both platforms
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] **Enable Gitea Actions on the Gitea instance** — ensure the Actions feature is enabled in `app.ini` (`[actions] ENABLED = true`) and restart Gitea
|
||||||
|
- [ ] **Set up a Gitea Actions runner** — deploy an `act_runner` container on Unraid (or the same host as Gitea), register it with the Gitea instance, and verify it picks up jobs
|
||||||
|
- [ ] **Create CI workflow** (`.github/workflows/ci.yml`) — on push to `develop` and PRs: lint, run tests (backend + frontend), and report status
|
||||||
|
- [ ] **Create deploy workflow** (`.github/workflows/deploy.yml`) — on push to `main`: build Docker images (linux/amd64), push to the Gitea container registry, and trigger redeployment on Unraid via SSH
|
||||||
|
- [ ] **Configure secrets in Gitea** — add repository or org-level secrets for registry credentials, SSH key/host for deployment, and any other sensitive values the workflows need
|
||||||
|
- [ ] **Test the full pipeline** — push a change through `feature/*` → `develop` → `main` and verify the CI and deploy workflows run successfully end-to-end
|
||||||
|
- [ ] **Update deployment docs** — document the Gitea Actions setup, how to manage the runner, and how CI/CD fits into the deployment workflow
|
||||||
@@ -1,18 +1,28 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-jzqz
|
# nuzlocke-tracker-jzqz
|
||||||
title: Configure Portainer webhook for automated redeployment
|
title: Configure Portainer API for automated redeployment
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
priority: normal
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:45Z
|
created_at: 2026-02-09T15:30:45Z
|
||||||
updated_at: 2026-02-09T15:31:15Z
|
updated_at: 2026-02-09T17:28:22Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
blocking:
|
blocking:
|
||||||
- nuzlocke-tracker-hwyk
|
- nuzlocke-tracker-hwyk
|
||||||
---
|
---
|
||||||
|
|
||||||
Set up a webhook in Portainer that triggers a stack redeployment when called.
|
Use the Portainer CE REST API to trigger stack redeployments from the deploy script.
|
||||||
|
|
||||||
- Create a webhook trigger in Portainer for the nuzlocke-tracker stack
|
Portainer webhooks are a Business-only feature, so we use the API directly instead.
|
||||||
- The webhook should pull the latest images from the local registry and restart the stack
|
|
||||||
- Note the webhook URL for use in the deploy script
|
## Approach
|
||||||
|
|
||||||
|
1. Authenticate with the Portainer API to get a JWT token
|
||||||
|
2. Call the stack update endpoint with `pullImage: true` to pull latest images and recreate containers
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Identify the stack ID in Portainer (via API or UI)
|
||||||
|
- [ ] Test API authentication (`POST /api/auth`)
|
||||||
|
- [ ] Test triggering a stack redeploy via API
|
||||||
|
- [ ] Integrate into the deploy script
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-jzw4
|
||||||
|
title: Switch prod compose to bind mounts for persistent data
|
||||||
|
status: completed
|
||||||
|
type: task
|
||||||
|
priority: normal
|
||||||
|
created_at: 2026-02-10T08:15:41Z
|
||||||
|
updated_at: 2026-02-10T08:16:44Z
|
||||||
|
parent: nuzlocke-tracker-ahza
|
||||||
|
---
|
||||||
|
|
||||||
|
Replace named Docker volume with bind mount to ./data/postgres subfolder. The docker-compose.prod.yml will live at /mnt/user/appdata/nuzlocke-tracker/ on Unraid, so relative paths resolve to subfolders there.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-lhls
|
||||||
|
title: Add compose file sync to deploy script
|
||||||
|
status: completed
|
||||||
|
type: task
|
||||||
|
priority: normal
|
||||||
|
created_at: 2026-02-10T08:19:57Z
|
||||||
|
updated_at: 2026-02-10T08:20:13Z
|
||||||
|
parent: nuzlocke-tracker-ahza
|
||||||
|
---
|
||||||
|
|
||||||
|
Update deploy.sh to SCP docker-compose.prod.yml to the Unraid server at /mnt/user/appdata/nuzlocke-tracker/ before triggering the Portainer redeployment. SSH target: root@192.168.1.10 (port 22).
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-q5vd
|
||||||
|
title: Explore automated data sources for encounter data
|
||||||
|
status: todo
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T08:58:47Z
|
||||||
|
updated_at: 2026-02-10T08:58:47Z
|
||||||
|
parent: nuzlocke-tracker-rzu4
|
||||||
|
---
|
||||||
|
|
||||||
|
Research and evaluate automated or semi-automated options for populating encounter data, especially for games where PokeAPI has no data (Gen 8+).
|
||||||
|
|
||||||
|
## Potential sources to investigate:
|
||||||
|
- **PokeAPI CSV/database dumps** — the raw data behind PokeAPI may have more than the REST API exposes
|
||||||
|
- **veekun/pokedex** — community-maintained Pokémon database with encounter data
|
||||||
|
- **Bulbapedia / Serebii** — structured wiki data that could be scraped (check terms of use)
|
||||||
|
- **pkNX / game data extraction** — tools that extract data directly from game files
|
||||||
|
- **Community GitHub repos** — search for curated encounter datasets (e.g. for romhack tools, fan wikis)
|
||||||
|
|
||||||
|
## Goals:
|
||||||
|
- Determine which games can realistically be populated via automation vs. manual entry
|
||||||
|
- If a viable source is found, prototype a script/tool to import data into the existing seed JSON format
|
||||||
|
- Document findings even if no automated approach is viable, so we know what's available
|
||||||
|
|
||||||
|
## Notes:
|
||||||
|
- The existing Go tool (`tools/fetch-pokeapi/`) could serve as a template for new data fetchers
|
||||||
|
- Output format must match the existing `{game}.json` structure (routes with encounters, children for sub-areas)
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-re0m
|
# nuzlocke-tracker-re0m
|
||||||
title: Document the deployment workflow
|
title: Document the deployment workflow
|
||||||
status: todo
|
status: in-progress
|
||||||
type: task
|
type: task
|
||||||
priority: normal
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:57Z
|
created_at: 2026-02-09T15:30:57Z
|
||||||
updated_at: 2026-02-09T15:31:15Z
|
updated_at: 2026-02-10T08:44:29Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
blocking:
|
blocking:
|
||||||
- nuzlocke-tracker-aiw6
|
- nuzlocke-tracker-aiw6
|
||||||
@@ -19,5 +19,7 @@ Write documentation covering the full deployment setup and workflows.
|
|||||||
- How to deploy (run `./deploy.sh`)
|
- How to deploy (run `./deploy.sh`)
|
||||||
- How to redeploy after changes
|
- How to redeploy after changes
|
||||||
- How to rollback to a previous version
|
- How to rollback to a previous version
|
||||||
- How to manage the production instance (Portainer UI, logs, etc.)
|
- How to manage the production instance (SSH, docker compose logs, etc.)
|
||||||
- How to set up the production environment from scratch (registry, Portainer, NPM, secrets)
|
- How to set up the production environment from scratch (registry auth, NPM, SSH access)
|
||||||
|
- Deploy script flow: build images (podman/docker) → push to Gitea registry → SCP compose file → generate .env if missing → pull and start containers via SSH
|
||||||
|
- Production files live at `/mnt/user/appdata/nuzlocke-tracker/` on Unraid (compose file, .env, data/)
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-rrcf
|
||||||
|
title: Set up backend test infrastructure
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
priority: normal
|
||||||
|
created_at: 2026-02-10T09:32:57Z
|
||||||
|
updated_at: 2026-02-10T09:33:59Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
blocking:
|
||||||
|
- nuzlocke-tracker-hjkk
|
||||||
|
- nuzlocke-tracker-iam7
|
||||||
|
- nuzlocke-tracker-ch77
|
||||||
|
- nuzlocke-tracker-ugb7
|
||||||
|
- nuzlocke-tracker-0arz
|
||||||
|
- nuzlocke-tracker-9c66
|
||||||
|
---
|
||||||
|
|
||||||
|
Set up the foundational test infrastructure for the FastAPI backend so that all subsequent test tasks can build on it.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Create `backend/tests/conftest.py` with shared fixtures
|
||||||
|
- [ ] Set up a test database strategy (use a separate test PostgreSQL database or SQLite for speed — evaluate trade-offs)
|
||||||
|
- [ ] Create an async test client fixture using `httpx.AsyncClient` with the FastAPI `app`
|
||||||
|
- [ ] Create a database session fixture that creates/drops tables per test session or uses transactions for isolation
|
||||||
|
- [ ] Add factory fixtures or helpers for creating common test entities (games, pokemon, runs, etc.)
|
||||||
|
- [ ] Verify the setup works by writing a simple smoke test (e.g. health endpoint returns 200)
|
||||||
|
- [ ] Document how to run tests (e.g. `pytest` from backend dir, any env vars needed)
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- pytest, pytest-asyncio, and httpx are already in pyproject.toml dev dependencies
|
||||||
|
- AsyncIO mode is set to "auto" in pyproject.toml
|
||||||
|
- The app uses SQLAlchemy async with asyncpg — test fixtures need to handle async session management
|
||||||
|
- Consider using `SAVEPOINT`-based transaction rollback for test isolation (faster than recreating tables)
|
||||||
31
.beans/nuzlocke-tracker-rzu4--game-data-cleanup.md
Normal file
31
.beans/nuzlocke-tracker-rzu4--game-data-cleanup.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-rzu4
|
||||||
|
title: Game Data Cleanup
|
||||||
|
status: todo
|
||||||
|
type: epic
|
||||||
|
created_at: 2026-02-10T08:58:36Z
|
||||||
|
updated_at: 2026-02-10T08:58:36Z
|
||||||
|
---
|
||||||
|
|
||||||
|
Audit and fix the game seed data to ensure all supported games have accurate encounter data and correct route ordering. PokeAPI provides a solid basis for Gen 1-7, but later games (Gen 8+) have no encounter data at all (stub/null JSON files), and route ordering is only defined for Gen 1-4. This is mostly manual work, but we should explore automated/semi-automated options where possible (e.g. scraping community wikis, leveraging existing fan-curated datasets).
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
### Encounter data status:
|
||||||
|
- **Complete (from PokeAPI):** Red, Blue, Yellow, FireRed, LeafGreen, Gold, Silver, Crystal, HeartGold, SoulSilver, Ruby, Sapphire, Emerald, Diamond, Pearl, Platinum, Black, White, Black 2, White 2, X, Y, Sun, Moon, Ultra Sun, Ultra Moon
|
||||||
|
- **Stub/null (no data):** Sword, Shield, Scarlet, Violet, Brilliant Diamond, Shining Pearl, Legends Arceus
|
||||||
|
- **Minimal/partial:** Omega Ruby, Alpha Sapphire (96 lines each), Let's Go Pikachu/Eevee (134 lines each), Legends Z-A (1298 lines, partially complete)
|
||||||
|
|
||||||
|
### Route ordering status (route_order.json):
|
||||||
|
- **Defined:** firered-leafgreen (+ aliases: red-blue, yellow, lets-go), heartgold-soulsilver (+ aliases: gold-silver, crystal), emerald (+ aliases: ruby-sapphire, omega-ruby-alpha-sapphire), platinum
|
||||||
|
- **Missing:** diamond-pearl, black-white, black-2-white-2, x-y, sun-moon, ultra-sun-ultra-moon, sword-shield, brilliant-diamond-shining-pearl, scarlet-violet, legends-arceus, legends-z-a
|
||||||
|
|
||||||
|
### Special considerations:
|
||||||
|
- Existing PokeAPI data may have inaccurate encounter rates or missing special encounters (gifts, fossils, starters)
|
||||||
|
- Sub-area grouping (children) may need review — some routes are split into too many/few sub-areas
|
||||||
|
- The `special_encounters.json` file handles manual additions but may be incomplete for later gens
|
||||||
|
|
||||||
|
## Approach
|
||||||
|
- Manual curation is the primary approach for most tasks
|
||||||
|
- Explore automated options: community datasets (e.g. veekun/pokedex, PokeAPI CSV data), wiki scraping, or other structured data sources
|
||||||
|
- Use the admin panel and export CLI to verify/edit data after seeding
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-ugb7
|
||||||
|
title: Integration tests for Pokemon & Evolutions API
|
||||||
|
status: draft
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:33:16Z
|
||||||
|
updated_at: 2026-02-10T09:33:16Z
|
||||||
|
parent: nuzlocke-tracker-yzpb
|
||||||
|
---
|
||||||
|
|
||||||
|
Write integration tests for the Pokemon and evolutions API endpoints.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Test Pokemon CRUD operations (create, list, search, update, delete)
|
||||||
|
- [ ] Test Pokemon filtering and search
|
||||||
|
- [ ] Test evolution chain CRUD (create, list, get, update, delete)
|
||||||
|
- [ ] Test evolution family resolution endpoint
|
||||||
|
- [ ] Test error cases (invalid Pokemon references, circular evolutions, etc.)
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Pokemon endpoints are in `backend/src/app/api/pokemon.py`
|
||||||
|
- Evolution endpoints are in `backend/src/app/api/evolutions.py`
|
||||||
|
- Evolution tests should cover multi-stage and branching chains
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-up0b
|
# nuzlocke-tracker-up0b
|
||||||
title: Environment and secrets management
|
title: Environment and secrets management
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:52Z
|
created_at: 2026-02-09T15:30:52Z
|
||||||
updated_at: 2026-02-09T15:30:52Z
|
updated_at: 2026-02-10T08:44:18Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-v5zc
|
||||||
|
title: Complete ORAS and Let's Go encounter data
|
||||||
|
status: todo
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T08:59:09Z
|
||||||
|
updated_at: 2026-02-10T08:59:09Z
|
||||||
|
parent: nuzlocke-tracker-rzu4
|
||||||
|
---
|
||||||
|
|
||||||
|
Omega Ruby, Alpha Sapphire, Let's Go Pikachu, and Let's Go Eevee have minimal stub data that needs to be completed.
|
||||||
|
|
||||||
|
## Current state:
|
||||||
|
- **Omega Ruby:** 96 lines (stub — likely just a skeleton)
|
||||||
|
- **Alpha Sapphire:** 96 lines (stub — likely just a skeleton)
|
||||||
|
- **Let's Go Pikachu:** 134 lines (minimal)
|
||||||
|
- **Let's Go Eevee:** 134 lines (minimal)
|
||||||
|
|
||||||
|
## Approach:
|
||||||
|
- **ORAS:** These are Gen 3 remakes. Emerald data could be used as a base, but ORAS added new areas (Mirage spots, soaring encounters), DexNav encounters, and different encounter tables. Supplement from community sources.
|
||||||
|
- **Let's Go:** These are Gen 1 remakes with simplified mechanics. FireRed/LeafGreen data could serve as a base, but encounters are different (no wild battles in traditional sense, overworld spawns). Version exclusives differ between Pikachu and Eevee versions.
|
||||||
|
|
||||||
|
## Checklist:
|
||||||
|
- [ ] Review and complete Omega Ruby encounter data
|
||||||
|
- [ ] Review and complete Alpha Sapphire encounter data
|
||||||
|
- [ ] Review and complete Let's Go Pikachu encounter data
|
||||||
|
- [ ] Review and complete Let's Go Eevee encounter data
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-vpn5
|
# nuzlocke-tracker-vpn5
|
||||||
title: Create production docker-compose file
|
title: Create production docker-compose file
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:41Z
|
created_at: 2026-02-09T15:30:41Z
|
||||||
updated_at: 2026-02-09T15:30:41Z
|
updated_at: 2026-02-09T16:59:00Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-xmyh
|
# nuzlocke-tracker-xmyh
|
||||||
title: Create production Dockerfiles
|
title: Create production Dockerfiles
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
|
priority: normal
|
||||||
created_at: 2026-02-09T15:30:42Z
|
created_at: 2026-02-09T15:30:42Z
|
||||||
updated_at: 2026-02-09T15:30:42Z
|
updated_at: 2026-02-09T17:00:32Z
|
||||||
parent: nuzlocke-tracker-ahza
|
parent: nuzlocke-tracker-ahza
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-xvaw
|
||||||
|
title: Clean up frontend branding and metadata
|
||||||
|
status: todo
|
||||||
|
type: task
|
||||||
|
created_at: 2026-02-10T09:36:24Z
|
||||||
|
updated_at: 2026-02-10T09:36:24Z
|
||||||
|
---
|
||||||
|
|
||||||
|
The frontend currently uses all Vite defaults — generic title, Vite favicon, no manifest, no meta tags. Clean it up so it looks polished and professional as "Nuzlocke Tracker".
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
- Page title: "frontend" (Vite default)
|
||||||
|
- Favicon: `/vite.svg` (Vite logo)
|
||||||
|
- No `manifest.json` / `site.webmanifest`
|
||||||
|
- No meta description or Open Graph tags
|
||||||
|
- No theme-color meta tag
|
||||||
|
- `package.json` name is "frontend"
|
||||||
|
- Default `react.svg` sitting unused in `src/assets/`
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Design or source a proper favicon (Pokeball-themed or similar, in SVG + PNG formats)
|
||||||
|
- [ ] Add favicon files to `public/` (favicon.ico, favicon.svg, apple-touch-icon.png, favicon-16x16.png, favicon-32x32.png)
|
||||||
|
- [ ] Update `index.html` title from "frontend" to "Nuzlocke Tracker"
|
||||||
|
- [ ] Add meta description tag (e.g. "Track your Nuzlocke challenge runs across all Pokemon games")
|
||||||
|
- [ ] Add theme-color meta tag matching the app's primary color
|
||||||
|
- [ ] Add Open Graph meta tags (og:title, og:description, og:type) for link previews
|
||||||
|
- [ ] Create a `site.webmanifest` with app name, short_name, icons, theme_color, background_color
|
||||||
|
- [ ] Link the manifest in `index.html`
|
||||||
|
- [ ] Remove unused default assets (`public/vite.svg`, `src/assets/react.svg`)
|
||||||
|
- [ ] Update `package.json` name from "frontend" to "nuzlocke-tracker" (or "nuzlocke-tracker-frontend")
|
||||||
|
- [ ] Consider adding dynamic page titles per route (e.g. "Runs | Nuzlocke Tracker") — optional stretch goal
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
# nuzlocke-tracker-yzpb
|
||||||
|
title: Implement Unit & Integration Tests
|
||||||
|
status: draft
|
||||||
|
type: epic
|
||||||
|
created_at: 2026-02-10T09:32:47Z
|
||||||
|
updated_at: 2026-02-10T09:32:47Z
|
||||||
|
---
|
||||||
|
|
||||||
|
Add comprehensive unit and integration test coverage to both the backend (FastAPI/Python) and frontend (React/TypeScript). The project currently has zero tests — pytest is configured in pyproject.toml with pytest-asyncio and httpx, but no actual test files exist. The frontend has no test tooling at all.
|
||||||
|
|
||||||
|
**Scope:**
|
||||||
|
- Unit tests for isolated logic (schemas, services, utilities)
|
||||||
|
- Integration tests for API endpoints (using httpx AsyncClient against a test database)
|
||||||
|
- Frontend unit/component tests (using Vitest + React Testing Library)
|
||||||
|
|
||||||
|
**Explicitly out of scope:**
|
||||||
|
- End-to-end / browser tests (e.g. Selenium, Playwright) — requires specialised infrastructure
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
- [ ] Backend test infrastructure is set up (conftest, fixtures, test DB)
|
||||||
|
- [ ] Backend schemas and services have unit test coverage
|
||||||
|
- [ ] Backend API endpoints have integration test coverage
|
||||||
|
- [ ] Frontend test infrastructure is set up (Vitest, RTL)
|
||||||
|
- [ ] Frontend utilities and hooks have unit test coverage
|
||||||
|
- [ ] Frontend components have basic render/interaction tests
|
||||||
152
DEPLOYMENT.md
Normal file
152
DEPLOYMENT.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Deployment
|
||||||
|
|
||||||
|
This document describes the deployment architecture and workflows for the nuzlocke-tracker. It is a living document — sections marked with **TODO** are planned but not yet implemented.
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
| Component | Dev (Laptop/PC) | Production (Unraid) |
|
||||||
|
|---|---|---|
|
||||||
|
| API | `docker-compose.yml` (hot reload) | `docker-compose.prod.yml` (built image) |
|
||||||
|
| Frontend | `docker-compose.yml` (Vite dev server) | `docker-compose.prod.yml` (built image) |
|
||||||
|
| Database | PostgreSQL 16 (Docker volume) | PostgreSQL 16 (Docker volume) |
|
||||||
|
| Container Registry | — | Gitea (user-level packages) |
|
||||||
|
| Container Management | — | Portainer CE |
|
||||||
|
| Reverse Proxy | — | Nginx Proxy Manager |
|
||||||
|
|
||||||
|
### Services
|
||||||
|
|
||||||
|
- **Gitea** — self-hosted Git server, container registry, and (future) CI/CD. Accessible at `gitea.nerdboden.de` via SSL.
|
||||||
|
- **Portainer** — Docker management UI. Accessible at `portainer.nerdboden.de` via SSL. Manages the production stack and provides webhook-triggered redeployments.
|
||||||
|
- **Nginx Proxy Manager** — reverse proxy with SSL termination for all services on the Unraid server.
|
||||||
|
|
||||||
|
## Container Registry
|
||||||
|
|
||||||
|
Docker images are hosted on Gitea's built-in container registry as **user-level packages**.
|
||||||
|
|
||||||
|
### Image naming
|
||||||
|
|
||||||
|
Images use the format `gitea.nerdboden.de/<user>/<image>:<tag>`:
|
||||||
|
|
||||||
|
```
|
||||||
|
gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
|
||||||
|
gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
1. Create a Gitea access token at **Settings > Applications** with `read:package` and `write:package` scopes.
|
||||||
|
2. Log in from the dev machine:
|
||||||
|
```bash
|
||||||
|
docker login gitea.nerdboden.de
|
||||||
|
```
|
||||||
|
Use your Gitea username and the access token as password.
|
||||||
|
|
||||||
|
### Pushing images
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and tag
|
||||||
|
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest ./backend
|
||||||
|
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest ./frontend
|
||||||
|
|
||||||
|
# Push
|
||||||
|
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
|
||||||
|
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Pushed images are visible under the **Packages** tab on your Gitea user profile.
|
||||||
|
|
||||||
|
## Branching Strategy
|
||||||
|
|
||||||
|
The project uses a `main` / `develop` / `feature/*` branching model.
|
||||||
|
|
||||||
|
| Branch | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `main` | Always production-ready. Deploy script builds from here. |
|
||||||
|
| `develop` | Integration branch for day-to-day work. |
|
||||||
|
| `feature/*` | Short-lived branches off `develop` for individual features/fixes. |
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
|
||||||
|
1. Create `feature/xyz` from `develop`
|
||||||
|
2. Work on the feature, commit, merge into `develop`
|
||||||
|
3. When ready to deploy: merge `develop` into `main`
|
||||||
|
4. Run the deploy script (see below)
|
||||||
|
|
||||||
|
## Deploying
|
||||||
|
|
||||||
|
> **TODO** — deploy script (`./deploy.sh`) not yet created.
|
||||||
|
|
||||||
|
The deploy script will automate:
|
||||||
|
|
||||||
|
1. Build Docker images from `main`
|
||||||
|
2. Tag and push to the Gitea container registry
|
||||||
|
3. Trigger the Portainer webhook to pull new images and restart the stack
|
||||||
|
|
||||||
|
### Manual deployment
|
||||||
|
|
||||||
|
Until the deploy script is in place, deploy manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Ensure you're on main with latest changes
|
||||||
|
git checkout main
|
||||||
|
|
||||||
|
# 2. Build and push images
|
||||||
|
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest ./backend
|
||||||
|
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest ./frontend
|
||||||
|
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
|
||||||
|
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
|
||||||
|
|
||||||
|
# 3. On Unraid (or via Portainer): pull and restart
|
||||||
|
docker compose -f docker-compose.prod.yml pull
|
||||||
|
docker compose -f docker-compose.prod.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Compose
|
||||||
|
|
||||||
|
> **TODO** — `docker-compose.prod.yml` not yet created.
|
||||||
|
|
||||||
|
The production compose file will differ from the dev compose in:
|
||||||
|
|
||||||
|
- Uses pre-built images from the Gitea registry (no source volume mounts)
|
||||||
|
- No hot reload / debug mode
|
||||||
|
- Production environment variables
|
||||||
|
- Proper restart policies
|
||||||
|
- Frontend served as a static build (not Vite dev server)
|
||||||
|
|
||||||
|
## Portainer
|
||||||
|
|
||||||
|
Portainer CE is running on Unraid at `portainer.nerdboden.de`.
|
||||||
|
|
||||||
|
- Manages the production Docker stack
|
||||||
|
- **TODO**: Configure a webhook for automated redeployment (pull latest images + restart on trigger)
|
||||||
|
|
||||||
|
## Nginx Proxy Manager
|
||||||
|
|
||||||
|
NPM runs on Unraid and handles SSL termination and routing for:
|
||||||
|
|
||||||
|
- `gitea.nerdboden.de` → Gitea
|
||||||
|
- `portainer.nerdboden.de` → Portainer
|
||||||
|
- **TODO**: `nuzlocke.nerdboden.de` (or similar) → nuzlocke-tracker frontend/API
|
||||||
|
|
||||||
|
## Environment & Secrets
|
||||||
|
|
||||||
|
> **TODO** — `.env.prod` template not yet created.
|
||||||
|
|
||||||
|
Production environment variables to configure:
|
||||||
|
|
||||||
|
- `DATABASE_URL` — PostgreSQL connection string
|
||||||
|
- `DEBUG` — must be `false` in production
|
||||||
|
- Additional secrets TBD
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
PostgreSQL 16 with data stored in a named Docker volume.
|
||||||
|
|
||||||
|
- Migrations run automatically on API container startup (Alembic)
|
||||||
|
- **TODO**: Set up scheduled backups (`pg_dump` cron job on Unraid)
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
> **TODO** — rollback procedure to be documented once image tagging strategy is finalized.
|
||||||
|
|
||||||
|
General approach: tag images with version/commit hash in addition to `latest`, so rolling back means redeploying a previous tag.
|
||||||
19
backend/Dockerfile.prod
Normal file
19
backend/Dockerfile.prod
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Production Dockerfile for the backend API
|
||||||
|
FROM python:3.14-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install Python dependencies
|
||||||
|
COPY pyproject.toml README.md alembic.ini ./
|
||||||
|
COPY src/ ./src/
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir .
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--app-dir", "src"]
|
||||||
80
deploy.sh
Executable file
80
deploy.sh
Executable file
@@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Configuration ──────────────────────────────────────────────
|
||||||
|
REGISTRY="gitea.nerdboden.de"
|
||||||
|
OWNER="thefurya"
|
||||||
|
IMAGES=("nuzlocke-tracker-api" "nuzlocke-tracker-frontend")
|
||||||
|
DOCKERFILES=("backend/Dockerfile.prod" "frontend/Dockerfile.prod")
|
||||||
|
CONTEXTS=("./backend" "./frontend")
|
||||||
|
|
||||||
|
if command -v podman &>/dev/null; then
|
||||||
|
CONTAINER_CMD="podman"
|
||||||
|
elif command -v docker &>/dev/null; then
|
||||||
|
CONTAINER_CMD="docker"
|
||||||
|
else
|
||||||
|
echo "Neither podman nor docker found." >&2; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
UNRAID_SSH="root@192.168.1.10"
|
||||||
|
UNRAID_DEPLOY_DIR="/mnt/user/appdata/nuzlocke-tracker"
|
||||||
|
|
||||||
|
# ── Helpers ────────────────────────────────────────────────────
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
info() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||||
|
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
||||||
|
error() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
|
||||||
|
|
||||||
|
# ── Preflight checks ──────────────────────────────────────────
|
||||||
|
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||||
|
if [[ "$BRANCH" != "main" ]]; then
|
||||||
|
warn "You are on branch '$BRANCH', not 'main'."
|
||||||
|
read -rp "Continue anyway? [y/N] " confirm
|
||||||
|
[[ "$confirm" =~ ^[Yy]$ ]] || exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||||
|
warn "You have uncommitted changes."
|
||||||
|
read -rp "Continue anyway? [y/N] " confirm
|
||||||
|
[[ "$confirm" =~ ^[Yy]$ ]] || exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Build and push images ─────────────────────────────────────
|
||||||
|
for i in "${!IMAGES[@]}"; do
|
||||||
|
IMAGE="${REGISTRY}/${OWNER}/${IMAGES[$i]}:latest"
|
||||||
|
info "Building ${IMAGES[$i]}..."
|
||||||
|
$CONTAINER_CMD build --platform linux/amd64 -t "$IMAGE" -f "${DOCKERFILES[$i]}" "${CONTEXTS[$i]}"
|
||||||
|
info "Pushing ${IMAGES[$i]}..."
|
||||||
|
$CONTAINER_CMD push "$IMAGE"
|
||||||
|
done
|
||||||
|
|
||||||
|
info "All images built and pushed."
|
||||||
|
|
||||||
|
# ── Sync compose file to Unraid ──────────────────────────────────
|
||||||
|
info "Copying docker-compose.prod.yml to Unraid..."
|
||||||
|
scp docker-compose.prod.yml "${UNRAID_SSH}:${UNRAID_DEPLOY_DIR}/docker-compose.yml" \
|
||||||
|
|| error "Failed to copy compose file to Unraid."
|
||||||
|
info "Compose file synced."
|
||||||
|
|
||||||
|
# ── Ensure .env with Postgres password exists ────────────────────
|
||||||
|
info "Checking for .env on Unraid..."
|
||||||
|
ssh "${UNRAID_SSH}" "
|
||||||
|
if [ ! -f '${UNRAID_DEPLOY_DIR}/.env' ]; then
|
||||||
|
PASS=\$(head -c 32 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 32)
|
||||||
|
echo \"POSTGRES_PASSWORD=\${PASS}\" > '${UNRAID_DEPLOY_DIR}/.env'
|
||||||
|
echo 'Generated new .env with POSTGRES_PASSWORD'
|
||||||
|
else
|
||||||
|
echo '.env already exists, skipping'
|
||||||
|
fi
|
||||||
|
" || error "Failed to check/create .env on Unraid."
|
||||||
|
|
||||||
|
# ── Pull images and (re)start on Unraid ──────────────────────────
|
||||||
|
info "Pulling images and starting containers on Unraid..."
|
||||||
|
ssh "${UNRAID_SSH}" "cd '${UNRAID_DEPLOY_DIR}' && docker compose pull && docker compose up -d" \
|
||||||
|
|| error "Failed to start containers on Unraid."
|
||||||
|
|
||||||
|
info "Deploy complete!"
|
||||||
36
docker-compose.prod.yml
Normal file
36
docker-compose.prod.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
services:
|
||||||
|
api:
|
||||||
|
image: gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
|
||||||
|
command: >
|
||||||
|
sh -c "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000 --app-dir src"
|
||||||
|
environment:
|
||||||
|
- DEBUG=false
|
||||||
|
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/nuzlocke
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
image: gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
|
||||||
|
ports:
|
||||||
|
- "9080:80"
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
|
- POSTGRES_DB=nuzlocke
|
||||||
|
volumes:
|
||||||
|
- ./data/postgres:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
21
frontend/Dockerfile.prod
Normal file
21
frontend/Dockerfile.prod
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Production Dockerfile for the frontend
|
||||||
|
# Stage 1: Build
|
||||||
|
FROM node:24-slim AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Stage 2: Serve
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
20
frontend/nginx.conf
Normal file
20
frontend/nginx.conf
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Proxy API requests to the backend service
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://api:8000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Serve static files, fall back to index.html for SPA routing
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -107,7 +107,7 @@ export function BossBattleFormModal({
|
|||||||
<label className="block text-sm font-medium mb-1">Type</label>
|
<label className="block text-sm font-medium mb-1">Type</label>
|
||||||
<select
|
<select
|
||||||
value={bossType}
|
value={bossType}
|
||||||
onChange={(e) => setBossType(e.target.value)}
|
onChange={(e) => setBossType(e.target.value as typeof bossType)}
|
||||||
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
||||||
>
|
>
|
||||||
{BOSS_TYPES.map((t) => (
|
{BOSS_TYPES.map((t) => (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
import { advanceLeg, createGenlocke, getGamesByRegion, getGenlockes, getGenlocke, getGenlockeGraveyard, getGenlockeLineages, getLegSurvivors } from '../api/genlockes'
|
import { advanceLeg, createGenlocke, getGamesByRegion, getGenlockes, getGenlocke, getGenlockeGraveyard, getGenlockeLineages, getLegSurvivors } from '../api/genlockes'
|
||||||
import type { AdvanceLegInput, CreateGenlockeInput } from '../types/game'
|
import type { CreateGenlockeInput } from '../types/game'
|
||||||
|
|
||||||
export function useGenlockes() {
|
export function useGenlockes() {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
|
|||||||
Reference in New Issue
Block a user