* Migrate frontend to SvelteKit with comprehensive deployment documentation - Create new SvelteKit project structure with routing, stores, and components - Implement complete authentication system with auth store and protected routes - Build all application pages: Home, Login, Register, Dashboard, Games, Stats, Commanders, Profile, and Round Counter - Configure Vite, TailwindCSS, PostCSS, and Nginx for production deployment - Add Dockerfile.svelte for containerized builds with multi-stage optimization - Create comprehensive SVELTE_DEPLOYMENT.md and SVELTE_MIGRATION.md guides - Update deployment scripts and package dependencies for SvelteKit ecosystem * feat: Add user authentication and game tracking pages to EDH Stats Tracker * Migrate frontend to SvelteKit and update Docker configuration - Replace Alpine.js with SvelteKit for improved DX and hot module replacement - Switch frontend service to `Dockerfile.dev` with volume mounts and Vite dev server - Update `docker-compose.yml` to map ports 5173 and use `http://localhost:5173` for CORS - Add `Dockerfile.svelte` for production static builds - Configure Vite proxy to target `http://backend:3000` in containers and `localhost:3002` locally - Migrate existing components to new routes and update authentication store logic - Add Chart.js integration to stats page and handle field name mapping for forms - Include static assets (`fonts/Beleren-Bold.ttf`) and update deployment scripts - Document migration status, testing checklist, and known minor issues in guides * Refactor frontend state properties from snake_case to camelCase This commit standardizes frontend property access across Dashboard, Games, and Stats pages. Changes include: - Renaming API data fields (e.g., `commanderName`, `playerCount`, `winRate`). - Updating `startEdit` logic to normalize mixed snake_case/camelCase inputs. - Replacing template literals like `_player_won` with camelCase versions. - Consistent usage of `totalGames` and `wins` instead of snake_case variants. * Update version to 2.1.12 and refactor commander management - Upgrade application version to 2.1.12 - Add Footer component and include in all pages - Refactor `/commanders` page to fetch commanders and stats separately - Fix commander API endpoint to load all commanders instead of only those with stats - Add stats merging logic to calculate wins, win rate, and avg rounds - Split add/edit command logic into shared `loadCommanders` function - Fix color toggle logic to work with both new and editing command modes - Update API methods for update requests to send `PUT` for existing commanders - Enhance commander delete functionality with proper API response handling - Refactor dashboard and stats pages to reuse shared data loading logic - Add chart cleanup on destroy for both dashboard and stats pages - Implement Chart.js for Win Rate by Color and Player Count charts - Reorganize round counter component state and timer functions - Add localStorage persistence for round counter with pause/resume support - Update game log page to integrate footer component * Refactor auth store and backend to use stable user ID * Backend: Switch user lookup from username to ID in auth routes to maintain stability across username changes. * Frontend: Update user store to reflect ID-based updates. * UI: Refactor user menu Svelte component to use ID-based user data. * Profile: Switch profile page to use ID-based user data for validation and state management. * format date formatting options consistently across dashboard and games pages * format date formatting options consistently across dashboard and games pages * Refactor card action buttons to use icons with semantic text - Switch "Edit" and "Delete" button text to SVG icons in `commanders` and `games` pages - Update icon colors and font styles to match standard design tokens (indigo/red, bold text) - Improve responsive spacing by adding `lg:grid-cols-3` * grids - Clarify hover states and titles for better UX accessibility Bump application versions to 2.2.0 and update deployment configuration * Convert `+page.svelte` to use template strings for multiline strings and fix syntax errors. * Update static version to 2.2.2 and tighten nginx cache headers
8.2 KiB
Docker Setup Guide
This project uses two different Docker Compose configurations for development and production environments.
🛠️ Development Setup (docker-compose.yml)
Purpose: Local development with hot reload and live code updates
Features
- ✅ Hot Reload: Code changes instantly reflected without rebuilding
- ✅ Volume Mounts: Source code mounted for real-time updates
- ✅ Vite Dev Server: Fast HMR (Hot Module Replacement)
- ✅ Development Dependencies: Includes all dev tools
Starting Development Environment
# Start all services (Postgres, Backend, Frontend)
docker compose up
# Start in detached mode
docker compose up -d
# Rebuild containers after dependency changes
docker compose up --build
# View logs
docker compose logs -f
# Stop services
docker compose down
Access Points
- Frontend Dev Server: http://localhost:5173 (Vite with hot reload)
- Backend API: http://localhost:3002
- PostgreSQL: localhost:5432
Important: CORS Configuration
The backend's CORS_ORIGIN is set to http://localhost:5173 in development to match the Vite dev server port. If you change the frontend port, you must also update the CORS_ORIGIN environment variable in docker-compose.yml.
How It Works
The frontend service:
- Uses
Dockerfile.devwhich runsnpm run dev - Mounts source directories as volumes
- Runs Vite dev server on port 5173
- Code changes trigger instant updates in the browser
Volume Mounts
volumes:
- ./frontend/src:/app/src # Svelte components
- ./frontend/static:/app/static # Static assets
- ./frontend/svelte.config.js:/app/svelte.config.js
- ./frontend/vite.config.js:/app/vite.config.js
- ./frontend/tailwind.config.js:/app/tailwind.config.js
- ./frontend/postcss.config.js:/app/postcss.config.js
- /app/node_modules # Exclude from mount
- /app/.svelte-kit # Exclude from mount
Common Development Commands
# Restart just the frontend after config changes
docker compose restart frontend
# Rebuild frontend after package.json changes
docker compose up --build frontend
# View frontend logs
docker compose logs -f frontend
# Shell into frontend container
docker compose exec frontend sh
# Run npm commands in container
docker compose exec frontend npm run build
docker compose exec frontend npm install <package>
🚀 Production Setup (docker-compose.prod.deployed.yml)
Purpose: Production deployment with optimized builds
Features
- ✅ Production Build: Optimized SvelteKit static build
- ✅ Nginx Server: Serves pre-built static files
- ✅ No Volume Mounts: Everything baked into the image
- ✅ Resource Limits: Memory and CPU constraints
- ✅ Traefik Integration: Automatic HTTPS with Let's Encrypt
Generation
The production compose file is automatically generated by:
-
GitHub Actions (
.github/workflows/publish.yml)- Runs on every push to
mainbranch - Builds Docker images
- Publishes to GitHub Container Registry
- Generates
docker-compose.prod.deployed.yml - Attaches to GitHub Release
- Runs on every push to
-
Local Script (
deploy.sh)./deploy.sh --build-local
Deployment
# Deploy to production
docker compose -f docker-compose.prod.deployed.yml up -d
# View logs
docker compose -f docker-compose.prod.deployed.yml logs -f
# Stop production
docker compose -f docker-compose.prod.deployed.yml down
# Update to new version
docker compose -f docker-compose.prod.deployed.yml pull
docker compose -f docker-compose.prod.deployed.yml up -d
Access Points
- Frontend: https://edh.zlor.fi (via Traefik)
- Backend API: http://localhost:3002
How It Works
The frontend service:
- Uses
Dockerfile.svelte(production multi-stage build) - Runs
npm run buildto create optimized static files - Serves via Nginx on port 80
- Includes cache headers and compression
- No source code in the container
📊 Comparison
| Feature | Development | Production |
|---|---|---|
| Compose File | docker-compose.yml |
docker-compose.prod.deployed.yml |
| Frontend Dockerfile | Dockerfile.dev |
Dockerfile.svelte |
| Frontend Server | Vite Dev Server | Nginx |
| Frontend Port | 5173 | 80 |
| Hot Reload | ✅ Yes | ❌ No |
| Volume Mounts | ✅ Yes | ❌ No |
| Build Time | Fast (no build) | Slower (full build) |
| File Size | Large | Small |
| Resource Usage | Higher | Lower |
| Cache Busting | Not needed | Automatic (Vite hashes) |
| HTTPS/Traefik | ❌ No | ✅ Yes |
🔧 Configuration Files
Development
docker-compose.yml- Main development compose filefrontend/Dockerfile.dev- Dev container with Vitefrontend/vite.config.js- Dev server config with API proxy
Production
docker-compose.prod.deployed.yml- Generated, do not editfrontend/Dockerfile.svelte- Production multi-stage buildfrontend/nginx.conf- Nginx configuration for SPA
🐛 Troubleshooting
Development Issues
Problem: Changes not reflecting
Solution: Check that volumes are mounted correctly
docker compose down
docker compose up --build
Problem: Port 5173 already in use
Solution: Change port in docker-compose.yml
ports:
- '5174:5173' # Use different external port
Problem: Frontend can't connect to backend / CORS errors
Solution: Ensure CORS_ORIGIN matches the frontend URL
# Check backend CORS configuration
docker compose logs backend | grep CORS
# Frontend is on port 5173, so backend needs:
# CORS_ORIGIN=http://localhost:5173
# Restart backend after changing CORS_ORIGIN
docker compose restart backend
Production Issues
Problem: Old code being served
Solution: Pull new images and restart
docker compose -f docker-compose.prod.deployed.yml pull
docker compose -f docker-compose.prod.deployed.yml up -d
Problem: 404 on page refresh
Solution: Check nginx.conf has SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
📝 Best Practices
Development Workflow
-
Start Docker services once:
docker compose up -d -
Code normally: Changes auto-reload in browser
-
After package.json changes:
docker compose down docker compose up --build frontend -
Before committing: Test production build
cd frontend npm run build
Production Deployment
- Let GitHub Actions build: Push to
mainbranch - Download compose file: From GitHub Release
- Deploy on server:
docker compose -f docker-compose.prod.deployed.yml pull docker compose -f docker-compose.prod.deployed.yml up -d
🔒 Environment Variables
Development (.env or docker-compose.yml)
# Database
DB_NAME=edh_stats
DB_USER=postgres
DB_PASSWORD=edh_password
# Backend
JWT_SECRET=dev-jwt-secret-change-in-production
CORS_ORIGIN=http://localhost
ALLOW_REGISTRATION=true
# Frontend
VITE_API_URL=http://localhost:3002
Production (.env on server)
# Database
DB_NAME=edh_stats
DB_USER=postgres
DB_PASSWORD=$(openssl rand -base64 32)
# Backend
JWT_SECRET=$(openssl rand -base64 32)
CORS_ORIGIN=https://yourdomain.com
ALLOW_REGISTRATION=false
LOG_LEVEL=warn
# No VITE_ vars needed - API proxy in nginx
🎯 Quick Reference
# Development
docker compose up # Start dev environment
docker compose logs -f frontend # Watch frontend logs
docker compose restart frontend # Restart after config change
docker compose down # Stop everything
# Production
docker compose -f docker-compose.prod.deployed.yml pull
docker compose -f docker-compose.prod.deployed.yml up -d
docker compose -f docker-compose.prod.deployed.yml logs -f