FigJam Diagram: D&D Multiplayer Platform Architecture (expires 2026-04-13)
AI-powered multiplayer Dungeons & Dragons platform with real-time voice, Discord integration, and AI dungeon mastering via AWS Bedrock.
| Namespace | dnd |
| Frontend | https://dnd.k3s.internal.strommen.systems |
| API | https://api.dnd.k3s.internal.strommen.systems |
| Voice | https://voice.dnd.k3s.internal.strommen.systems (LiveKit WSS) |
| Auth | Google OAuth2 + Discord OAuth2 (not Authentik) |
| Images | harbor.k3s.internal.strommen.systems/production/dnd-{backend,frontend,discord-bot} |
| Component | Image | Port | Purpose |
|---|---|---|---|
dnd-backend |
production/dnd-backend:sha-<commit> |
8000 | FastAPI REST + WebSocket API |
dnd-frontend |
production/dnd-frontend:sha-<commit> |
3000 | Next.js SSR/SPA app |
dnd-discord-bot |
production/dnd-discord-bot:sha-<commit> |
8001 | Discord gateway bot + /metrics |
livekit |
livekit/livekit-server:latest |
7880 | WebRTC voice/video room server |
postgres |
pgvector/pgvector:pg16 |
5432 | PostgreSQL + pgvector for AI embeddings |
redis |
redis:7-alpine |
6379 | Session + WebSocket state |
pgvector enables vector similarity search over campaign notes, NPC descriptions, etc.
Policy violation:
livekit/livekit-server:latestand Harbor images use:latest— cluster policy requiressha-<commit>tags. Pin viapromote-image.ymlwhen stabilizing for production.
| Role | Model ID | Purpose |
|---|---|---|
| DM (Dungeon Master) | us.anthropic.claude-3-5-haiku-20241022-v1:0 |
Fast DM narration |
| Narrator | us.anthropic.claude-3-5-sonnet-20241022-v2:0 |
Rich story narration |
| Image Generation | amazon.titan-image-generator-v2:0 |
Scene/map image generation |
| Embeddings | amazon.titan-embed-text-v2:0 |
pgvector semantic search |
Auth is handled natively by the backend — not through Authentik forwardAuth:
/api/auth/google/callback/api/auth/discord/callback| Secret | Keys | Purpose |
|---|---|---|
postgres-credentials |
POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB |
Database access |
dnd-secrets |
SECRET_KEY, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_BOT_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, LIVEKIT_API_KEY, LIVEKIT_API_SECRET |
App credentials |
Bootstrap:
kubectl create secret generic postgres-credentials --namespace dnd \
--from-literal=POSTGRES_USER=dndapp \
--from-literal=POSTGRES_PASSWORD="$(openssl rand -hex 16)" \
--from-literal=POSTGRES_DB=dndmulti
kubectl create secret generic dnd-secrets --namespace dnd \
--from-literal=SECRET_KEY="$(openssl rand -hex 32)" \
--from-literal=GOOGLE_CLIENT_ID=<value> \
--from-literal=GOOGLE_CLIENT_SECRET=<value> \
--from-literal=DISCORD_CLIENT_ID=<value> \
--from-literal=DISCORD_CLIENT_SECRET=<value> \
--from-literal=DISCORD_BOT_TOKEN=<value> \
--from-literal=AWS_ACCESS_KEY_ID=<value> \
--from-literal=AWS_SECRET_ACCESS_KEY=<value> \
--from-literal=LIVEKIT_API_KEY=<value> \
--from-literal=LIVEKIT_API_SECRET=<value>
| Volume | Type | Size | Purpose |
|---|---|---|---|
postgres-data |
Longhorn RWO | 10Gi | PostgreSQL + pgvector data |
| Redis | emptyDir | — | Ephemeral session state |
| Schedule | Daily 3:25 AM UTC |
| Method | pg_dump → gzip → s3://k3s-homelab-backups-855878721457/postgres-backups/dnd/ |
| Retention | 7 days |
| Manifest | kubernetes/apps/dnd/postgres-backup-cronjob.yaml |
Uses
pgvector/pgvector:pg16as the base — pg_dump is agnostic to base image; pgvector extension data is included in the dump.
Backend exposes Prometheus metrics via pod annotations (prometheus.io/scrape: "true", port 8000, path /metrics). ServiceMonitor label: release: prometheus. No dedicated Grafana dashboard yet.
kubernetes/apps/dnd/
dnd.yaml — Namespace, PostgreSQL, Redis, backend+frontend+bot+LiveKit Deployments,
Services, Ingresses, ConfigMap, ServiceMonitor, RBAC
postgres-backup-cronjob.yaml — Daily PostgreSQL backup to S3