Files
edh-stats/DOCKER_SETUP.md
Michael d69a14d80b Migrate frontend to SvelteKit with comprehensive deployment (#2)
* 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
2026-04-11 10:42:46 +02:00

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

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.dev which runs npm 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:

  1. GitHub Actions (.github/workflows/publish.yml)

    • Runs on every push to main branch
    • Builds Docker images
    • Publishes to GitHub Container Registry
    • Generates docker-compose.prod.deployed.yml
    • Attaches to GitHub Release
  2. 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

How It Works

The frontend service:

  • Uses Dockerfile.svelte (production multi-stage build)
  • Runs npm run build to 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 file
  • frontend/Dockerfile.dev - Dev container with Vite
  • frontend/vite.config.js - Dev server config with API proxy

Production

  • docker-compose.prod.deployed.yml - Generated, do not edit
  • frontend/Dockerfile.svelte - Production multi-stage build
  • frontend/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

  1. Start Docker services once:

    docker compose up -d
    
  2. Code normally: Changes auto-reload in browser

  3. After package.json changes:

    docker compose down
    docker compose up --build frontend
    
  4. Before committing: Test production build

    cd frontend
    npm run build
    

Production Deployment

  1. Let GitHub Actions build: Push to main branch
  2. Download compose file: From GitHub Release
  3. 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

📚 Additional Resources