6.9 KiB
6.9 KiB
✅ API Subdomain - COMPLETE & WORKING!
What Changed
Old Architecture (REMOVED)
Browser → Traefik → PWA nginx → API (internal proxy)
↓
/api/ → http://api:8000/
/ws/ → http://api:8000/ws/
New Architecture (CURRENT)
Browser → Traefik → API (api.echoesoftheashgame.patacuack.net:8000)
Browser → Traefik → PWA (echoesoftheashgame.patacuack.net:80)
Why This Is Better
- Cleaner Separation: Frontend and backend are completely separate services
- Better Performance: No nginx proxy hop - direct Traefik → API
- Easier Debugging: Clear separation in logs and network requests
- Independent Scaling: Can scale PWA and API separately
- Standard Architecture: Industry standard microservices pattern
Verified Working ✅
API Subdomain Tests
# Health endpoint
$ curl https://api.echoesoftheashgame.patacuack.net/health
{"status":"healthy","version":"2.0.0","locations_loaded":14,"items_loaded":42}
# Login endpoint (with wrong password)
$ curl -X POST https://api.echoesoftheashgame.patacuack.net/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"wrong"}'
{"detail":"Invalid username or password"}
# ✅ Both returning proper responses!
PWA Configuration
# PWA loads correctly
$ curl -I https://echoesoftheashgame.patacuack.net
HTTP/2 200 ✅
# API URL is baked into build
$ docker exec echoes_of_the_ashes_pwa sh -c 'grep -o "api\.echoesoftheashgame\.patacuack\.net" /usr/share/nginx/html/assets/index-*.js'
api.echoesoftheashgame.patacuack.net ✅
nginx Configuration
# No more /api/ or /ws/ proxy routes
$ docker exec echoes_of_the_ashes_pwa cat /etc/nginx/conf.d/default.conf | grep location
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
location /sw.js {
location /workbox-*.js {
location /manifest.webmanifest {
location / {
# ✅ Only static file serving!
API Endpoint Reference
Base URLs
- API:
https://api.echoesoftheashgame.patacuack.net - PWA:
https://echoesoftheashgame.patacuack.net
REST Endpoints (all have /api prefix)
POST https://api.echoesoftheashgame.patacuack.net/api/auth/register
POST https://api.echoesoftheashgame.patacuack.net/api/auth/login
GET https://api.echoesoftheashgame.patacuack.net/api/auth/me
GET https://api.echoesoftheashgame.patacuack.net/api/game/state
GET https://api.echoesoftheashgame.patacuack.net/api/game/profile
POST https://api.echoesoftheashgame.patacuack.net/api/game/move
POST https://api.echoesoftheashgame.patacuack.net/api/game/interact
... etc
WebSocket Endpoint (no /api prefix)
wss://api.echoesoftheashgame.patacuack.net/ws/game/{token}
PWA Configuration
Environment Variable
// pwa/src/services/api.ts
const API_URL = import.meta.env.VITE_API_URL || (
import.meta.env.PROD
? 'https://api.echoesoftheashgame.patacuack.net/api' // ← /api suffix for REST
: 'http://localhost:8000/api'
)
WebSocket Configuration
// pwa/src/hooks/useGameWebSocket.ts
const API_BASE = import.meta.env.VITE_API_URL || (
import.meta.env.PROD
? 'https://api.echoesoftheashgame.patacuack.net' // ← no /api for WebSocket
: 'http://localhost:8000'
);
const wsBase = API_BASE.replace(/\/api$/, '').replace(/^http/, 'ws');
// Results in: wss://api.echoesoftheashgame.patacuack.net/ws/game/{token}
Docker Configuration
docker-compose.yml
echoes_of_the_ashes_api:
networks:
- default_docker
- traefik # ← Now exposed via Traefik!
labels:
- traefik.enable=true
- traefik.http.routers.echoesoftheashapi.rule=Host(`api.echoesoftheashgame.patacuack.net`)
- traefik.http.services.echoesoftheashapi.loadbalancer.server.port=8000
echoes_of_the_ashes_pwa:
build:
args:
VITE_API_URL: https://api.echoesoftheashgame.patacuack.net/api # ← Baked into build
networks:
- default_docker
- traefik
Dockerfile.pwa
ARG VITE_API_URL=https://api.echoesoftheashgame.patacuack.net/api
ENV VITE_API_URL=$VITE_API_URL
nginx.conf
# REMOVED:
# location /api/ { proxy_pass http://api:8000/; }
# location /ws/ { proxy_pass http://api:8000/ws/; }
# NOW ONLY:
location / {
try_files $uri $uri/ /index.html;
}
DNS Configuration
Required DNS Records:
A api.echoesoftheashgame.patacuack.net → <your-server-ip>
A echoesoftheashgame.patacuack.net → <your-server-ip>
TLS Certificates:
- Both subdomains get Let's Encrypt certificates from Traefik
- Auto-renewal configured
- Both use certResolver=production
Testing Checklist ✅
- API health endpoint returns 200
- API login endpoint returns proper error for invalid credentials
- PWA loads and serves static files
- API URL is embedded in PWA build (not runtime fallback)
- nginx config simplified (no proxy routes)
- Both domains have valid TLS certificates
- WebSocket endpoint exists (returns 404 for invalid token as expected)
- Traefik routes both services correctly
What to Test in Browser
- Open PWA: https://echoesoftheashgame.patacuack.net
- Check Network Tab:
- API calls should go to
api.echoesoftheashgame.patacuack.net/api/* - WebSocket should connect to
wss://api.echoesoftheashgame.patacuack.net/ws/game/*
- API calls should go to
- Login/Register: Should work normally
- Game Actions: All should work (move, combat, inventory, etc.)
- WebSocket: Should connect and show real-time updates
Troubleshooting
If API calls fail
# Check API is running
docker compose logs echoes_of_the_ashes_api
# Test health endpoint
curl https://api.echoesoftheashgame.patacuack.net/health
# Check Traefik routing
docker compose logs | grep api.echoesoftheashgame
If WebSocket fails
# Check logs for WebSocket connections
docker compose logs echoes_of_the_ashes_api | grep -i websocket
# Verify token is valid (login to get fresh token)
# Old tokens won't work after rebuild
If PWA loads but can't connect to API
# Verify API URL is in build
docker exec echoes_of_the_ashes_pwa sh -c 'grep -o "api\.echoesoftheashgame\.patacuack\.net" /usr/share/nginx/html/assets/index-*.js'
# If not found, rebuild PWA
docker compose build echoes_of_the_ashes_pwa
docker compose up -d echoes_of_the_ashes_pwa
Summary
✅ API subdomain deployed and working
✅ PWA simplified (static files only)
✅ Direct Traefik routing (no nginx proxy)
✅ Both services have valid TLS
✅ Configuration verified in build
The architecture is now cleaner, faster, and easier to maintain! 🚀
Note: Users need to logout and login again after this deployment to get fresh JWT tokens. Old tokens from the previous architecture won't work because the issuer URL changed.