This document reflects the current code layout under /tmp/pokecollector.
| Layer | Technology | Port |
|---|---|---|
| Frontend | React 18 + Vite + Tailwind CSS | 3000 |
| Backend | FastAPI | 8000 |
| Database | PostgreSQL 15 | 5432 |
| External APIs | TCGdex, Gemini, Frankfurter, GitHub | external |
| Containerization | Docker + docker compose | - |
pokecollector/
├── backend/
│ ├── main.py
│ ├── database.py
│ ├── models.py
│ ├── schemas.py
│ ├── api/
│ │ ├── auth.py
│ │ ├── backup.py
│ │ ├── binders.py
│ │ ├── cards.py
│ │ ├── collection.py
│ │ ├── dashboard.py
│ │ ├── export.py
│ │ ├── github.py
│ │ ├── images.py
│ │ ├── products.py
│ │ ├── recognize.py
│ │ ├── settings.py
│ │ ├── sets.py
│ │ ├── social.py
│ │ ├── sync.py
│ │ └── wishlist.py
│ └── services/
│ ├── auth.py
│ ├── pokemon_api.py
│ ├── scheduler.py
│ ├── sync_service.py
│ └── telegram.py
├── frontend/
│ ├── src/
│ │ ├── api/client.js
│ │ ├── components/
│ │ │ ├── AppNav.jsx
│ │ │ ├── CardItem.jsx
│ │ │ ├── CardScanner.jsx
│ │ │ ├── Layout.jsx
│ │ │ └── TabNav.jsx
│ │ ├── contexts/
│ │ │ ├── AuthContext.jsx
│ │ │ └── SettingsContext.jsx
│ │ ├── hooks/
│ │ │ └── useTheme.js
│ │ ├── i18n/
│ │ │ ├── de.js
│ │ │ ├── en.js
│ │ │ └── zh.js
│ │ └── pages/
│ └── index.html
├── docs/
├── SUPPORTERS.csv
├── docker-compose.yml
└── README.md
Removed from the current architecture:
- no
backend/api/ebay.py - no
services/notifications.py - no old nested
pokemon-tcg-collection/directory
backend/main.py registers feature routers under /api/*.
Important modules added since the older docs:
api/auth.pyapi/github.py
Key ORM models in backend/models.py:
SetCardUserCollectionItemWishlistItemBinderBinderCardProductPurchaseSyncLogPortfolioSnapshotSettingUserSettingCustomCardMatchImageCache
Notable current model rules:
Set.idandCard.idare composite ids with language suffixesCard.raritycomes from TCGdex and is treated as read-only metadata- Collection variants are limited to physical print variants
User.must_change_passworddrives the forced password change flowUserSettingstores per-user preferences and secrets
Settings are split between two stores:
- Global
settingstable - Per-user
user_settingstable
The split is defined in backend/api/settings.py:
PER_USER_KEYS- language
- currency
- price display preferences
- Telegram keys and alert preferences
- Gemini key
- trainer name
ADMIN_ONLY_KEYS- full sync interval
- price sync interval
- multi-user mode
- TCGdex sync languages
Effectively:
- normal users can only change their own per-user settings
- admins can also change global operational settings
- per-user settings isolation is enforced in the API layer
Authentication lives in:
backend/api/auth.pybackend/services/auth.pyfrontend/src/contexts/AuthContext.jsx
Current auth model:
- Single-user mode returns the admin user from
get_current_user()when no token is present - Multi-user mode requires JWT authentication
/api/auth/modeexposes whether the app is in single-user or multi-user modemust_change_passwordis returned by/api/auth/loginand/api/auth/me- The frontend blocks protected routes until forced password change is completed
Recognition is implemented in backend/api/recognize.py and surfaced in frontend/src/components/CardScanner.jsx.
Current flow:
- User uploads or captures a card image
- Gemini extracts card name, English name, printed number, set hint, type, HP, and language
- Search terms are broadened by stripping suffixes such as
EX,GX,V,VMAX,VSTAR,TAG TEAM,BREAK, andLV.X - TCGdex search results are collected in the detected language, with English fallback when needed
- Results are ranked by printed card number
- If number ranking is not decisive, Gemini visually compares the top candidates and picks the best match
The frontend then lets the user choose quantity, condition, variant, language, and purchase price before adding to the collection.
Current frontend state layers:
- Server state: TanStack Query
- Auth state:
AuthContext - Settings and i18n state:
SettingsContext - Local UI state: component-level
useState - Theme state:
useThemewithdata-themeand local storage
AuthContext is now a core part of the app architecture, not an optional enhancement.
HomeScreen.jsxis the compact portal entry pointLayout.jsxwraps protected routesAppNav.jsxprovides the page title strip and logout affordanceTabNav.jsxis the shared section tab component used across major screens
- Set and card source of truth
- Variant availability flags come from TCGdex
- Rarity is read from TCGdex and shown read-only
- Used for smart scanner recognition
- Key is read per user from
user_settings
- Implemented in
backend/services/telegram.py - Service accepts
user_idso alerts use that user's Telegram credentials
backend/api/github.pyfetches contributors from the GitHub API- Supporters are read from
SUPPORTERS.csv frontend/src/pages/Settings.jsxrenders both in the Community section
- Sync endpoints are admin-only
- Backup and restore are admin-only
- Settings keys are separated into admin-only and per-user scopes
- Frontend logout clears local storage and forces a full reload to avoid leaking cached user data across sessions
- User deletion explicitly removes owned rows from collection, wishlist, binders, products, portfolio snapshots, and user settings before deleting the user
Schema changes are handled by idempotent SQL in backend/database.py, not Alembic.
Some migration comments still mention historical features, but the current runtime architecture does not include eBay integration and does not expose grading in the active UI or ORM model.