CLAUDE: Add multi-domain environment configuration support

- 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>
This commit is contained in:
Cal Corum 2025-12-03 13:58:42 -06:00
parent db667965e6
commit 7d28eebd24
12 changed files with 237 additions and 15 deletions

View File

@ -22,6 +22,8 @@ DATABASE_URL=postgresql+asyncpg://paperdynasty:your-password@your-db-server:5432
DISCORD_CLIENT_ID=your-discord-client-id
DISCORD_CLIENT_SECRET=your-discord-client-secret
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
# ============================================================================
# League REST APIs
@ -39,9 +41,28 @@ PD_API_KEY=your-pd-api-key
# ============================================================================
CORS_ORIGINS=http://localhost:3000,http://localhost:3001
# ============================================================================
# Access Control
# ============================================================================
# Comma-separated Discord user IDs allowed access
# Leave empty or use * for all users (dev only!)
ALLOWED_DISCORD_IDS=
# ============================================================================
# WebSocket Settings
# ============================================================================
WS_HEARTBEAT_INTERVAL=30
WS_CONNECTION_TIMEOUT=60
# ============================================================================
# Redis (optional - for caching)
# ============================================================================
# When using Docker Compose, Redis is automatically available at redis://redis:6379
# When running locally, use redis://localhost:6379
# REDIS_URL=redis://localhost:6379
# ============================================================================
# Frontend Dev Server
# ============================================================================
# Comma-separated hostnames for Vite dev server external access
NUXT_ALLOWED_HOSTS=localhost,127.0.0.1

View File

@ -81,9 +81,52 @@ strat-gameplay-webapp/
│ └── tests/
├── frontend-sba/ # SBA League Nuxt app
├── frontend-pd/ # PD League Nuxt app
└── shared-components/ # Shared Vue components (optional)
├── docker-compose.yml # Dev orchestration (all services)
├── docker-compose.prod.yml # Production overrides
└── .env.example # Root environment template
```
## Environment Configuration
### Multi-Domain Support
The project is fully environment-driven for deployment to different domains. All URLs and credentials are externalized.
### Environment Files
| File | Purpose |
|------|---------|
| `.env.example` | Root template - copy to `.env` |
| `backend/.env.example` | Backend-specific template |
| `frontend-sba/.env.example` | SBA frontend template |
| `frontend-pd/.env.example` | PD frontend template |
### Key Environment Variables
**Backend** (in `backend/.env`):
- `DATABASE_URL` - PostgreSQL connection string
- `DISCORD_CLIENT_ID/SECRET` - OAuth credentials
- `DISCORD_SERVER_REDIRECT_URI` - Server-side OAuth callback
- `FRONTEND_URL` - Frontend base URL for redirects
- `CORS_ORIGINS` - Allowed origins (comma-separated)
- `ALLOWED_DISCORD_IDS` - User whitelist (comma-separated, empty = all)
**Frontend** (in `frontend-*/env`):
- `NUXT_PUBLIC_API_URL` - Backend API URL
- `NUXT_PUBLIC_WS_URL` - WebSocket URL
- `NUXT_PUBLIC_DISCORD_CLIENT_ID` - OAuth client ID (public)
- `NUXT_PUBLIC_DISCORD_REDIRECT_URI` - OAuth callback URL
- `NUXT_ALLOWED_HOSTS` - Vite dev server allowed hosts (comma-separated)
### Docker Deployment
```bash
# Development
docker compose up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
See `README.md` "Multi-Domain Deployment" section for full checklist.
## Development Guidelines
### Code Quality

View File

@ -208,6 +208,47 @@ Copy `.env.example` to `.env` and configure:
- `REDIS_URL` - Redis connection (auto-configured in Docker)
- `CORS_ORIGINS` - Allowed origins (defaults to localhost:3000,3001)
---
## Multi-Domain Deployment
This project supports deployment to multiple domains. Key environment variables to configure:
### Backend Variables
| Variable | Description | Example |
|----------|-------------|---------|
| `FRONTEND_URL` | Frontend base URL for OAuth redirects | `https://yourdomain.com` |
| `DISCORD_REDIRECT_URI` | Legacy Discord callback | `https://yourdomain.com/auth/callback` |
| `DISCORD_SERVER_REDIRECT_URI` | Server-side Discord callback | `https://yourdomain.com/api/auth/discord/callback/server` |
| `CORS_ORIGINS` | Allowed CORS origins (comma-separated) | `https://yourdomain.com,https://api.yourdomain.com` |
| `ALLOWED_DISCORD_IDS` | Whitelist of Discord user IDs | `123456,789012` or empty for all |
### Frontend Variables
| Variable | Description | Example |
|----------|-------------|---------|
| `NUXT_PUBLIC_API_URL` | Backend API base URL | `https://yourdomain.com` |
| `NUXT_PUBLIC_WS_URL` | WebSocket base URL | `https://yourdomain.com` |
| `NUXT_PUBLIC_DISCORD_REDIRECT_URI` | OAuth callback URL | `https://yourdomain.com/auth/callback` |
| `NUXT_ALLOWED_HOSTS` | Vite dev server allowed hosts (comma-separated) | `yourdomain.com,localhost` |
### Production Deployment
```bash
# Using Docker Compose with production overrides
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
### Domain Deployment Checklist
When deploying to a new domain:
1. [ ] Update Discord OAuth redirect URIs in [Discord Developer Portal](https://discord.com/developers/applications)
2. [ ] Copy `.env.example` files to `.env` and configure all URLs
3. [ ] Update `CORS_ORIGINS` to include new domain
4. [ ] Add domain to `NUXT_ALLOWED_HOSTS` (if using dev server externally)
5. [ ] Configure reverse proxy (Nginx/NPM) to route traffic
---
## Available Services
When running, the following services are available:

View File

@ -75,14 +75,36 @@ now = pendulum.now('UTC')
- **Database**: paperdynasty_dev
- **Connection**: `postgresql+asyncpg://...`
### Required .env Variables
### Environment Variables
Copy `.env.example` to `.env` and configure. Key variables:
```bash
DATABASE_URL=postgresql+asyncpg://...
SECRET_KEY=your-secret-key
DISCORD_CLIENT_ID=...
DISCORD_CLIENT_SECRET=...
# 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)

28
docker-compose.prod.yml Normal file
View File

@ -0,0 +1,28 @@
# Production overrides for Paper Dynasty Game Engine
# Usage: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
services:
backend:
build:
target: production
environment:
- APP_ENV=production
- DEBUG=false
restart: always
frontend-sba:
build:
target: production
environment:
- NODE_ENV=production
restart: always
frontend-pd:
build:
target: production
environment:
- NODE_ENV=production
restart: always
redis:
restart: always

View File

@ -2,8 +2,6 @@
# Use this for integration testing, demos, or when you want everything containerized
# For daily dev, see README.md for local development workflow
version: '3.8'
services:
# Redis cache (shared dependency)
redis:
@ -51,6 +49,17 @@ services:
# CORS
- CORS_ORIGINS=http://localhost:3000,http://localhost:3001
# Server-side OAuth
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:3000}
- DISCORD_SERVER_REDIRECT_URI=${DISCORD_SERVER_REDIRECT_URI:-http://localhost:8000/api/auth/discord/callback/server}
# Access Control
- ALLOWED_DISCORD_IDS=${ALLOWED_DISCORD_IDS:-}
# WebSocket Settings
- WS_HEARTBEAT_INTERVAL=${WS_HEARTBEAT_INTERVAL:-30}
- WS_CONNECTION_TIMEOUT=${WS_CONNECTION_TIMEOUT:-60}
depends_on:
redis:
condition: service_healthy
@ -79,6 +88,7 @@ services:
- NUXT_PUBLIC_WS_URL=http://localhost:8000
- NUXT_PUBLIC_DISCORD_CLIENT_ID=${DISCORD_CLIENT_ID}
- NUXT_PUBLIC_DISCORD_REDIRECT_URI=http://localhost:3000/auth/callback
- NUXT_ALLOWED_HOSTS=${NUXT_ALLOWED_HOSTS:-localhost,127.0.0.1}
depends_on:
backend:
condition: service_healthy
@ -103,6 +113,7 @@ services:
- NUXT_PUBLIC_WS_URL=http://localhost:8000
- NUXT_PUBLIC_DISCORD_CLIENT_ID=${DISCORD_CLIENT_ID}
- NUXT_PUBLIC_DISCORD_REDIRECT_URI=http://localhost:3001/auth/callback
- NUXT_ALLOWED_HOSTS=${NUXT_ALLOWED_HOSTS:-localhost,127.0.0.1}
depends_on:
backend:
condition: service_healthy

14
frontend-pd/.env.example Normal file
View File

@ -0,0 +1,14 @@
# PD League Frontend Configuration
# Copy to .env and update with your values
# API Configuration
NUXT_PUBLIC_API_URL=http://localhost:8000
NUXT_PUBLIC_WS_URL=http://localhost:8000
# Discord OAuth (public client ID only - safe to expose)
NUXT_PUBLIC_DISCORD_CLIENT_ID=your-discord-client-id
NUXT_PUBLIC_DISCORD_REDIRECT_URI=http://localhost:3001/auth/callback
# Vite Dev Server - Allowed external hosts (comma-separated)
# Add your domain here for external access during development
NUXT_ALLOWED_HOSTS=localhost,127.0.0.1

View File

@ -257,16 +257,24 @@ export const useGameStore = defineStore('game', () => {
## Configuration
### Environment Variables
Create `.env` file with:
Copy `.env.example` to `.env` and configure:
```bash
NUXT_PUBLIC_LEAGUE_ID=pd
NUXT_PUBLIC_LEAGUE_NAME=Paper Dynasty
# API endpoints
NUXT_PUBLIC_API_URL=http://localhost:8000
NUXT_PUBLIC_WS_URL=http://localhost:8000
# Discord OAuth (public client ID - safe to expose)
NUXT_PUBLIC_DISCORD_CLIENT_ID=your-client-id
NUXT_PUBLIC_DISCORD_REDIRECT_URI=http://localhost:3001/auth/callback
# Vite dev server allowed hosts (comma-separated)
# Add your domain for external access
NUXT_ALLOWED_HOSTS=localhost,127.0.0.1
```
**Note**: `NUXT_ALLOWED_HOSTS` is read in `nuxt.config.ts` to configure Vite's `allowedHosts`. Required when accessing dev server through a reverse proxy or external domain.
### Nuxt Config
```typescript
// nuxt.config.ts

View File

@ -16,6 +16,14 @@ export default defineNuxtConfig({
devtools: { enabled: true },
// Vite config for external hostname access
// Configure NUXT_ALLOWED_HOSTS env var for your domains (comma-separated)
vite: {
server: {
allowedHosts: process.env.NUXT_ALLOWED_HOSTS?.split(',') || ['localhost', '127.0.0.1']
}
},
typescript: {
strict: true,
typeCheck: true

14
frontend-sba/.env.example Normal file
View File

@ -0,0 +1,14 @@
# SBA League Frontend Configuration
# Copy to .env and update with your values
# API Configuration
NUXT_PUBLIC_API_URL=http://localhost:8000
NUXT_PUBLIC_WS_URL=http://localhost:8000
# Discord OAuth (public client ID only - safe to expose)
NUXT_PUBLIC_DISCORD_CLIENT_ID=your-discord-client-id
NUXT_PUBLIC_DISCORD_REDIRECT_URI=http://localhost:3000/auth/callback
# Vite Dev Server - Allowed external hosts (comma-separated)
# Add your domain here for external access during development
NUXT_ALLOWED_HOSTS=localhost,127.0.0.1

View File

@ -58,14 +58,25 @@ npm run lint # Lint code
## Configuration
### Environment Variables (.env)
### Environment Variables
Copy `.env.example` to `.env` and configure:
```bash
NUXT_PUBLIC_LEAGUE_ID=sba
# API endpoints
NUXT_PUBLIC_API_URL=http://localhost:8000
NUXT_PUBLIC_WS_URL=http://localhost:8000
# Discord OAuth (public client ID - safe to expose)
NUXT_PUBLIC_DISCORD_CLIENT_ID=your-client-id
NUXT_PUBLIC_DISCORD_REDIRECT_URI=http://localhost:3000/auth/callback
# Vite dev server allowed hosts (comma-separated)
# Add your domain for external access
NUXT_ALLOWED_HOSTS=localhost,127.0.0.1
```
**Note**: `NUXT_ALLOWED_HOSTS` is read in `nuxt.config.ts` to configure Vite's `allowedHosts`. Required when accessing dev server through a reverse proxy or external domain.
### League Theme
- Primary: #1e40af (SBA Blue)
- Secondary: #dc2626 (SBA Red)

View File

@ -31,9 +31,10 @@ export default defineNuxtConfig({
},
// Vite config for external hostname access
// Configure NUXT_ALLOWED_HOSTS env var for your domains (comma-separated)
vite: {
server: {
allowedHosts: ['gameplay-demo.manticorum.com', 'localhost', '127.0.0.1']
allowedHosts: process.env.NUXT_ALLOWED_HOSTS?.split(',') || ['localhost', '127.0.0.1']
}
},