3.2 KiB
WikiTCG
A trading card game where every card is procedurally generated from a Wikipedia article. Players open booster packs, build decks, trade with each other, and play real-time matches over WebSocket.
- Backend — FastAPI (
backend/), PostgreSQL, SQLAlchemy + Alembic - Frontend — SvelteKit with the static adapter (
frontend/) - External — Wikipedia API (card generation), Resend (email), Stripe (payments)
Running locally
# Backend — dev server on :8000
cd backend
pip install -r requirements.txt
uvicorn main:app --reload
# Frontend — dev server on :5173
cd frontend
npm install
npm run dev
Tests and checks:
cd backend && pytest test_game.py # game logic
cd frontend && npm run check # svelte-check
Deployment
The stack runs as three Docker Compose services (db, backend, frontend)
behind Nginx Proxy Manager. No service publishes a port; NPM reaches the
containers by name over an external proxy network. The database sits on a
second network marked internal: true, so it has no route off the host.
git pull && docker compose up -d --build
Database and migrations
The database has two roles, and they are not interchangeable:
| Role | Used by | Rights |
|---|---|---|
wikitcg_app |
the running app, via DATABASE_URL |
SELECT/INSERT/UPDATE/DELETE — no DDL |
wikitcg |
Alembic only, via MIGRATION_DATABASE_URL |
owns the schema |
Migrations therefore run as wikitcg, never as the app role:
docker compose run --rm backend alembic upgrade head # apply
docker compose run --rm backend alembic revision --autogenerate -m "description"
alembic/env.py reads MIGRATION_DATABASE_URL and fails loudly if it is
unset. There is deliberately no fallback to DATABASE_URL: the app role has no
DDL rights, so falling back would surface as a confusing permissions error partway
through a migration instead of an obvious configuration error up front.
sqlalchemy.url in alembic.ini is intentionally empty — the URL comes from the
environment so no credential lives in version control.
The split needs no sequence grants: every primary key is either a client-generated UUID or a string.
Environment variables
Set in .env at the repo root (untracked). See backend/core/config.py.
Required — the app refuses to start without these:
| Variable | Notes |
|---|---|
JWT_SECRET_KEY |
signing key for access and refresh tokens |
DATABASE_URL |
app role (wikitcg_app) |
RESEND_API_KEY, EMAIL_FROM |
transactional email |
STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET |
payments |
Required for migrations:
| Variable | Notes |
|---|---|
MIGRATION_DATABASE_URL |
schema owner (wikitcg) — Alembic only |
Optional:
| Variable | Default | Notes |
|---|---|---|
FRONTEND_URL |
http://localhost:5173 |
links in outbound email |
CORS_ORIGINS |
http://localhost:5173 |
comma-separated |
WIKIRANK_USER_AGENT |
WikiTCG/1.0 |
sent to the Wikipedia API |
ENABLE_DOCS |
unset (disabled) | set to exactly true to serve /docs, /redoc and /openapi.json. Any other value leaves them disabled, so a new environment fails closed. |