Pokedexter ⚡
Pokémon TCG-samlerwebapp — bygget med FastAPI, PostgreSQL 16, Nginx og Podman/Docker.
Administratorer opretter serier, sæt og kort. Brugere kan logge ind, browse og søge. Ingen åben registrering.
Arkitektur
Browser ──► Nginx (:8085) ──► FastAPI (:8000) ──► PostgreSQL (:5432)
▲ │
└─── static/ ───────┘
- Nginx — reverse proxy, serverer statiske filer på port 8085
- FastAPI — async Python backend, Jinja2 templates
- PostgreSQL 16 — database med SQLAlchemy (async/asyncpg)
Kom i gang
Billeder bygges lokalt først, deploy sker via Portainer.
Byg lokalt (podman)
podman build -t pokedexter-backend:latest -f backend/Dockerfile backend/
podman build -t pokedexter-nginx:latest -f nginx/Dockerfile nginx/
Start lokalt
podman-compose up -d # podman
docker compose up -d # docker
Stop
podman-compose down
docker compose down
Data i volumes (pokedexter_pgdata, pokedexter_images) bevares mellem genstarter.
Login
| Brugernavn | Adgangskode | Rolle |
|---|---|---|
admin |
admin123 |
Admin |
Brugeren oprettes automatisk ved første opstart. Skift adgangskoden efter første login.
Sådan bruges det
Opret en serie
- Log ind på
/loginmedadmin/admin123 - Gå til Admin → Serier
- Indtast navn (f.eks.
Sword & Shield) og evt. beskrivelse - Tryk Opret
Opret sæt under en serie
- Gå til Admin → Serier
- Klik på serienavnet (link)
- Indtast kode (f.eks.
EVS), navn (Evolving Skies) og evt. release_date - Tryk Opret sæt
Eller bulk import: indsæt CSV direkte i tekstfeltet:
Stellar Crown,SCR,Stellar Crown,2024-09-13,
Surging Sparks,SSP,Surging Sparks,2024-11-08,
Tilføj kort
- Gå til Admin → Sæt
- Klik Vis kort på det ønskede sæt
- Udfyld nummer, navn og evt. image URL
- Tryk Opret kort
Eller bulk import via CSV:
SCR,001,Caterpie,https://images.pokemontcg.io/scarlet_ivy/1.png
SCR,002,Metapod,
Kortet får automatisk koden SCR-001.
Billedhåndtering
Når en URL angives ved kortoprettelse:
- Billedet downloades automatisk og gemmes lokalt i volume'et
- Hvis download fejler, bevares URL'en som
image_pathog et ⚠-badge vises Card.image_urlreturnerer aldrig eksterne URLs — ingen streaming
Synkronisér billeder
På Admin → Sæt → Vis kort findes en Synkronisér billeder-knap, der downloader alle eksterne billeder for sættet til lokal lagring.
Verificér & genopret
På Admin-dashboardet findes:
- Verificér & genopret — tjekker om alle lokale billedfiler findes på disken. Manglende filer re-downloades fra
source_url - Force-genhent alle — genhenter ALLE billeder fra deres originale kilder (uanset om de findes)
Dette er nyttigt hvis volume'et afmonteres ved en fejl, eller billeder tabes ved genstart.
Opret brugere (admin)
På Admin-dashboardet under "Brugere" kan du oprette og slette brugere. Du kan ikke slette dig selv.
Browse kort
/sets— liste alle serier med sæt/sets/{code}— se alle kort i sætEVS/card/{full_code}— detaljer om et specifikt kort
Søg
/search?q=SCR-001— søg på fuld kortkode/search?q=pikachu— søg på kortnavn
API-oversigt
Offentlige endpoints
| Metode | Sti | Beskrivelse |
|---|---|---|
| GET | / |
Forside |
| GET | /sets |
Liste alle serier |
| GET | /sets/{code} |
Kort i et sæt |
| GET | /search |
Søgeside |
| GET | /api/search |
Søg (JSON) |
| GET | /api/cards/{full_code} |
Enkelt kort (JSON) |
Auth endpoints
| Metode | Sti | Beskrivelse |
|---|---|---|
| GET | /login |
Loginside |
| POST | /api/login |
Login (sætter cookie) |
| GET | /logout |
Logout |
Admin endpoints (kræver admin)
| Metode | Sti | Beskrivelse |
|---|---|---|
| GET | /admin |
Admin dashboard |
| GET | /admin/series |
Administrér serier |
| GET | /admin/series/{name} |
Serie-detail med sæt |
| GET | /admin/sets |
Administrér sæt |
| GET | /admin/sets/{code} |
Administrér kort i sæt |
| POST | /api/admin/users |
Opret bruger |
| DELETE | /api/admin/users/{id} |
Slet bruger (ikke dig selv) |
| POST | /api/admin/series |
Opret serie |
| POST | /api/admin/series/csv |
Bulk import af serier (CSV) |
| DELETE | /api/admin/series/{id} |
Slet serie |
| POST | /api/admin/series/{name}/sets |
Opret sæt under serie |
| POST | /api/admin/series/{name}/sets/csv |
Bulk import af sæt (CSV) |
| POST | /api/admin/sets/{code}/cards |
Opret kort |
| POST | /api/admin/sets/{code}/cards/csv |
Bulk import af kort (CSV) |
| DELETE | /api/admin/cards/{id} |
Slet kort |
| POST | /api/admin/cards/{id}/upload |
Upload billede (fil) |
| POST | /api/admin/sets/{code}/sync-images |
Synkronisér billeder for sæt |
| POST | /api/admin/sync-all-images |
Synkronisér alle billeder |
| POST | /api/admin/verify-images |
Verificér og genopret billeder |
| POST | /api/admin/verify-images?force=true |
Force-genhent alle billeder |
Datamodel
User
id Integer (PK)
username String (unique)
password_hash String (bcrypt)
role String ("admin" | "user")
created_at DateTime
Serie
id Integer (PK)
name String (unique) — "Sword & Shield"
description Text (optional)
created_at DateTime
sets ► Set[]
Set
id Integer (PK)
serie_id Integer (FK → series.id)
code String (unique) — "EVS"
name String — "Evolving Skies"
release_date String (optional)
description Text (optional)
created_at DateTime
serie ► Serie
cards ► Card[]
Card
id Integer (PK)
set_id Integer (FK → sets.id)
number String — "050"
name String — "Raichu"
image_path String (optional) — lokal sti eller URL
source_url String (optional) — original ekstern URL til re-sync
set ► Set
full_code [property] — "EVS-050"
image_url [property] — "/static/..." eller None (ingen eksterne URLs)
Miljøvariable
| Variabel | Standard | Beskrivelse |
|---|---|---|
DATABASE_URL |
postgresql+asyncpg://... |
PostgreSQL forbindelse |
SECRET_KEY |
skift-mig-til-en-sikker-noegle |
JWT signeringsnøgle |
Projektstruktur
pokedexter/
├── docker-compose.yml
├── start.sh # podman start
├── stop.sh # podman stop
├── README.md
├── backend/
│ ├── Dockerfile
│ ├── requirements.txt
│ └── app/
│ ├── main.py # FastAPI app, middleware
│ ├── database.py # async engine + session
│ ├── models.py # SQLAlchemy modeller
│ ├── auth.py # bcrypt + JWT
│ ├── static/
│ │ └── images/ # uploadet/downloadede billeder (volume)
│ ├── templates/ # Jinja2 HTML templates
│ │ ├── base.html # layout m. dark mode toggle
│ │ └── admin/ # admin UI templates
│ └── routers/
│ ├── auth.py # login/logout + admin user mgmt
│ ├── admin.py # admin CRUD for series/sets/cards
│ └── cards.py # browse + search
├── nginx/
│ ├── Dockerfile
│ └── nginx.conf
└── db/
└── init.sql
Udvikling
Genstart backend efter kodeændringer
# Byg nyt image
podman build -t pokedexter-backend:latest -f backend/Dockerfile backend/
# Genstart via Portainer, eller:
podman stop pokedexter-backend && podman rm pokedexter-backend
podman-compose up -d backend
Dark mode
Dark mode gemmes i localStorage og sættes via render-blokerende script i <head> — ingen flash ved side-skift.
Billeder og volumes
Billeder gemmes i volume pokedexter_images mountet på /app/static/images.
Volume'et skal være mountet før første hentning — ellers går billeder tabt ved container-genstart.
Hvis billeder mangler: brug Verificér & genopret på admin-dashboardet.
Køreplan / To-do
- Søgning optimeres — PostgreSQL full-text search (tsvector/tsquery) eller trigram similarity (pg_trgm). Nuværende LIKE-søgning rammer ikke forkortelser, delvise navne eller stavefejl (
ar→Arceus,pika→Pikachu) - Opdater billede på kort — admin skal kunne ændre source-billed-URL på et eksisterende kort, hvorefter billedet re-downloades og lokale sti opdateres
- Galleri/bladring i sæt — vis kortbilleder i et sæt som et galleri/carousel, så man kan bladre frem/tilbage uden at gå til listen
- Personlig mappe — brugere kan markere kort de ejer/samler
- Filtrering på type, sjældenhed, HP
- Kort-detalje side med artwork
- Eksport af samling til CSV