- Create frontend-sba/.env.example and frontend-pd/.env.example templates - Fix hardcoded allowedHosts in nuxt.config.ts (now reads NUXT_ALLOWED_HOSTS) - Add NUXT_ALLOWED_HOSTS support to frontend-pd/nuxt.config.ts - Update docker-compose.yml with missing env vars: - FRONTEND_URL, DISCORD_SERVER_REDIRECT_URI - ALLOWED_DISCORD_IDS, WS_HEARTBEAT_INTERVAL, WS_CONNECTION_TIMEOUT - NUXT_ALLOWED_HOSTS for both frontends - Create docker-compose.prod.yml for production overrides - Update root .env.example with new variables - Add "Multi-Domain Deployment" section to README.md with checklist - Update all CLAUDE.md files with environment configuration docs - Remove obsolete 'version' attribute from docker-compose files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
148 lines
4.6 KiB
Markdown
148 lines
4.6 KiB
Markdown
# Backend - Paper Dynasty Game Engine
|
|
|
|
## Overview
|
|
|
|
FastAPI-based real-time game backend handling WebSocket communication, game state management, and database persistence for both SBA and PD leagues.
|
|
|
|
**Tech Stack**: FastAPI (Python 3.13), Socket.io, PostgreSQL 14+, SQLAlchemy 2.0, Pydantic v2, pytest
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
backend/
|
|
├── app/
|
|
│ ├── main.py # FastAPI + Socket.io init
|
|
│ ├── config.py # pydantic-settings
|
|
│ ├── core/ # Game engine - see core/CLAUDE.md
|
|
│ ├── config/ # League configs - see config/CLAUDE.md
|
|
│ ├── models/ # Pydantic + SQLAlchemy - see models/CLAUDE.md
|
|
│ ├── websocket/ # Socket.io handlers - see websocket/CLAUDE.md
|
|
│ ├── api/ # REST endpoints - see api/CLAUDE.md
|
|
│ ├── database/ # Async persistence - see database/CLAUDE.md
|
|
│ ├── services/ # Business logic (LineupService, PD API client)
|
|
│ └── utils/ # Logging, auth - see utils/CLAUDE.md
|
|
├── tests/ # See tests/CLAUDE.md
|
|
├── terminal_client/ # Interactive testing - see terminal_client/CLAUDE.md
|
|
└── logs/ # Daily rotating logs (gitignored)
|
|
```
|
|
|
|
## Development
|
|
|
|
### Quick Start
|
|
```bash
|
|
cd backend
|
|
uv sync # Install dependencies
|
|
uv run alembic upgrade head # Apply database migrations
|
|
uv run python -m app.main # Start server at localhost:8000
|
|
```
|
|
|
|
### Testing
|
|
```bash
|
|
uv run pytest tests/unit/ -v # All unit tests (836 passing)
|
|
uv run python -m terminal_client # Interactive REPL
|
|
```
|
|
|
|
### Code Quality
|
|
```bash
|
|
uv run mypy app/ # Type checking
|
|
uv run ruff check app/ # Linting
|
|
uv run ruff format app/ # Formatting
|
|
```
|
|
|
|
## Key Patterns
|
|
|
|
### Hybrid State Management
|
|
- **In-memory**: Active game states for <500ms response
|
|
- **PostgreSQL**: Persistent storage for recovery
|
|
- **Pattern**: Write-through cache (update memory + async DB write)
|
|
|
|
### League-Agnostic Core
|
|
- Game engine works for any league
|
|
- Config-driven behavior (SbaConfig, PdConfig)
|
|
- Polymorphic player models (BasePlayer → SbaPlayer, PdPlayer)
|
|
|
|
### DateTime
|
|
**Always use Pendulum** (never Python's datetime):
|
|
```python
|
|
import pendulum
|
|
now = pendulum.now('UTC')
|
|
```
|
|
|
|
## Environment
|
|
|
|
### Database
|
|
- **Server**: PostgreSQL at 10.10.0.42:5432
|
|
- **Database**: paperdynasty_dev
|
|
- **Connection**: `postgresql+asyncpg://...`
|
|
|
|
### Environment Variables
|
|
Copy `.env.example` to `.env` and configure. Key variables:
|
|
|
|
```bash
|
|
# Required
|
|
DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/db
|
|
SECRET_KEY=your-secret-key-min-32-chars
|
|
DISCORD_CLIENT_ID=your-discord-client-id
|
|
DISCORD_CLIENT_SECRET=your-discord-client-secret
|
|
|
|
# OAuth URLs (update for your domain)
|
|
DISCORD_REDIRECT_URI=http://localhost:3000/auth/callback
|
|
DISCORD_SERVER_REDIRECT_URI=http://localhost:8000/api/auth/discord/callback/server
|
|
FRONTEND_URL=http://localhost:3000
|
|
|
|
# Access Control
|
|
ALLOWED_DISCORD_IDS= # Comma-separated user IDs, empty = all users
|
|
|
|
# CORS (JSON array format)
|
|
CORS_ORIGINS=["http://localhost:3000","http://localhost:3001"]
|
|
|
|
# League APIs
|
|
SBA_API_URL=https://api.sba.manticorum.com
|
|
SBA_API_KEY=your-sba-api-key
|
|
PD_API_URL=https://pd-api.example.com
|
|
PD_API_KEY=your-pd-api-key
|
|
```
|
|
|
|
**Multi-Domain Deployment**: When deploying to a new domain, update `FRONTEND_URL`, `DISCORD_*_REDIRECT_URI`, and `CORS_ORIGINS`. See root `README.md` for full checklist.
|
|
|
|
### Python Environment
|
|
- **Version**: Python 3.13.3
|
|
- **Package Manager**: UV (fast, reliable)
|
|
- **Virtual Environment**: `backend/.venv/`
|
|
|
|
## Testing Policy
|
|
|
|
**REQUIRED**: 100% unit tests passing before any commit
|
|
```bash
|
|
uv run pytest tests/unit/ -q # Must show all passing
|
|
```
|
|
|
|
## Coding Standards
|
|
|
|
- **Formatting**: Ruff (88 chars, black-compatible)
|
|
- **Linting**: Ruff (replaces flake8, includes isort, pyupgrade)
|
|
- **Type Hints**: Required for public functions
|
|
- **Logging**: `logger = logging.getLogger(f'{__name__}.ClassName')`
|
|
- **Error Handling**: "Raise or Return" - no silent failures
|
|
|
|
## Performance Targets
|
|
|
|
| Metric | Target |
|
|
|--------|--------|
|
|
| Action response | < 500ms |
|
|
| WebSocket delivery | < 200ms |
|
|
| DB writes | < 100ms (async) |
|
|
| State recovery | < 2 seconds |
|
|
|
|
## References
|
|
|
|
- **WebSocket Protocol Spec**: `../.claude/WEBSOCKET_PROTOCOL_SPEC.md` - Complete event catalog and workflow
|
|
- **Type Checking Guide**: `.claude/type-checking-guide.md`
|
|
- **Code Review**: `.claude/CODE_REVIEW_GAME_ENGINE.md`
|
|
- **Implementation Plans**: `../.claude/implementation/`
|
|
- **Full PRD**: `../prd-web-scorecard-1.1.md`
|
|
|
|
---
|
|
|
|
**Tests**: 836 passing | **Phase**: 3E-Final Complete | **Updated**: 2025-01-27
|