Files
Dimension-47/CLAUDE.md

28 KiB
Raw Blame History

Dimension47 - TTRPG Campaign Management Platform

Projekt-Philosophie

Qualität vor Geschwindigkeit: Es ist egal, wie lange die Implementierung dauert - das System soll am Ende gut funktionieren. Keine Shortcuts oder Quick-Fixes, die später Probleme verursachen.

Lieber langsam und richtig: Immer den sauberen Weg wählen, auch wenn er länger dauert. Beispiele:

  • Prisma Migrations statt db push verwenden
  • Daten in Datenbank statt direkt aus JSON-Dateien lesen
  • Proper Error Handling statt try/catch mit console.log
  • TypeScript strict mode, keine any Types

Architektur-Entscheidungen

Daten-Management

  • Equipment/Items in Datenbank: Alle Pathfinder 2e Daten (Waffen, Rüstungen, Ausrüstung, Zauber, Talente) werden in die PostgreSQL-Datenbank importiert, NICHT direkt aus JSON-Dateien gelesen.
  • Prisma Seed Scripts: JSON-Dateien werden via prisma db seed in die Datenbank importiert.
  • Übersetzungen gecacht: Deutsche Übersetzungen werden on-demand via Claude API generiert und in der Translation-Tabelle gespeichert.

Vorteile des Database-Ansatzes

  • Bessere Such- und Filtermöglichkeiten
  • Konsistente Datenstruktur
  • Eigene Items können hinzugefügt werden
  • Relationale Verknüpfungen möglich
  • Performance durch Indizes

Tech Stack

Frontend

  • React 19 + TypeScript
  • Vite als Build Tool
  • Tailwind CSS v4
  • shadcn/ui Komponenten (selbst gebaut)
  • Zustand für Client State

Backend

  • NestJS mit TypeScript
  • Prisma ORM
  • PostgreSQL
  • JWT Authentication
  • Socket.io für WebSockets

Ordnerstruktur

dimension47/
├── client/                 # React Frontend
│   ├── src/
│   │   ├── app/           # App-Config, Router
│   │   ├── features/      # Feature-Module (auth, campaigns, characters, etc.)
│   │   │   ├── auth/components/
│   │   │   │   ├── login-page.tsx            # Login mit Animationen
│   │   │   │   └── register-page.tsx         # Registrierung
│   │   │   └── characters/
│   │   │       ├── components/
│   │   │       │   ├── character-sheet-page.tsx  # Hauptseite mit Tabs
│   │   │       │   ├── hp-control.tsx            # HP-Management Komponente
│   │   │       │   ├── add-condition-modal.tsx   # Zustand hinzufügen
│   │   │       │   ├── add-item-modal.tsx        # Item aus DB hinzufügen
│   │   │       │   ├── actions-tab.tsx           # Aktionen-Tab
│   │   │       │   ├── alchemy-tab.tsx           # Alchemie-Tab
│   │   │       │   └── rest-modal.tsx            # Rasten-Modal
│   │   │       └── utils/
│   │   │           └── export-character-html.ts  # HTML-Export Funktion
│   │   ├── shared/        # Geteilte Komponenten, Hooks, Types
│   │   │   └── hooks/
│   │   │       └── use-character-socket.ts   # WebSocket Hook für Echtzeit-Sync
│   │   └── assets/
│   └── public/            # Statische Dateien, JSON-Datenbanken
│
└── server/                 # NestJS Backend
    ├── src/
    │   ├── modules/       # Feature-Module
    │   │   ├── auth/      # Authentifizierung
    │   │   ├── campaigns/ # Kampagnenverwaltung
    │   │   ├── characters/# Charakterverwaltung
    │   │   │   ├── characters.gateway.ts  # WebSocket Gateway
    │   │   │   └── alchemy.service.ts     # Alchemie-System Service
    │   │   └── equipment/ # Equipment-Datenbank
    │   ├── common/        # Shared Utilities
    │   └── prisma/        # Prisma Service
    └── prisma/
        ├── schema.prisma  # Datenbank-Schema
        ├── migrations/    # Prisma Migrations
        ├── seed.ts        # Basis-Seed
        ├── seed-equipment.ts # Equipment-Import (5.482 Items)
        └── data/          # JSON-Quelldaten für Equipment

Implementierte Features

Auth

  • JWT-basierte Authentifizierung
  • Login/Register/Logout
  • Rollen: ADMIN, GM, PLAYER
  • "Anmeldung speichern" Funktion (localStorage vs sessionStorage)
  • Animierter Login-Screen:
    • Zweistufiger Flow: Splash → Formular
    • Animierter Sternenhintergrund mit schwebenden Orbs
    • "DIMENSION 47" Titel mit Buchstaben-Animation und Glow-Effekt
    • Logo mit Tap-Glow-Effekt
    • Gestaffelte Formular-Animationen (Komponente für Komponente)

Kampagnen

  • CRUD für Kampagnen
  • Mitgliederverwaltung
  • GM-Berechtigungen

Charaktere

  • Pathbuilder 2e Import
  • HP-Management (mobile-optimiert, Schaden/Heilung/Direkt)
  • Zustände (Conditions) mit PF2e-Datenbank
  • Fertigkeiten mit deutschen Namen
  • Rettungswürfe
  • Inventar-System (komplett):
    • Vollständige Equipment-Datenbank (5.482 Items)
    • Item-Suche mit Kategoriefilter und Pagination
    • Bulk-Tracking mit Belastungs-Anzeige
    • Ausrüstungsstatus (angelegt/abgelegt/investiert)
    • Quantity-Management
    • Item-Details mit Eigenschaften, Schaden, etc.
    • Benutzerdefinierte Notizen pro Item
  • Talente-Tab (komplett):
    • Alle Charaktertalente aus Pathbuilder-Import
    • Kategorisiert nach Quelle (Klasse, Abstammung, Allgemein, Fertigkeit, Bonus, Archetyp)
    • Einklappbare Kategorien
    • Talentdetails mit Beschreibung und Voraussetzungen
  • Aktionen-Tab mit PF2e-Aktionsdatenbank (99 Aktionen)
    • Kategorien: Allgemein, Kampf, Bewegung, Interaktion, Spezial
    • Einklappbare Kategorien (standardmäßig eingeklappt)
    • Aktionstyp-Icons (Aktion, Reaktion, Freie Aktion, etc.)
    • Suchfunktion
  • WebSocket Real-Time Sync für:
    • HP (aktuell, temporär, max)
    • Zustände (hinzufügen, entfernen, aktualisieren)
    • Inventar (Items hinzufügen, entfernen, aktualisieren)
    • Ausrüstungsstatus (angelegt/abgelegt)
    • Geld (Credits)
    • Level
    • Alchemie (Phiolen, Formeln, vorbereitete Items)
  • Alchemie-Tab (komplett):
    • Vielseitige Phiolen mit Tracker
    • Formelbuch mit allen bekannten Formeln
    • Tägliche Vorbereitung (Advanced Alchemy)
    • Schnelle Alchemie (Quick Alchemy)
    • Handwerkliche Alchemie (Craft Alchemy)
    • Forschungsgebiete (Bomber, Chirurg, Mutageniker, Toxikologe)
    • Infundierte Items mit Effekt-Anzeige und Schadenswerten
  • Rest-System:
    • HP-Heilung basierend auf CON-Mod × Level
    • Zustands-Management (Erschöpft entfernt, Verdammt/Entkräftet reduziert)
    • Ressourcen-Reset (Zauberplätze, Fokuspunkte)
    • Alchemie-Reset (infundierte Items verfallen, Phiolen aufgefüllt)
  • Status-Tab Erweiterungen:
    • Wahrnehmung mit korrekter PF2e-Berechnung
    • Geschwindigkeit
    • Rüstungsklasse mit Übungsstufe
    • Rettungswürfe mit Übungsstufen
  • HTML-Export:
    • Vollständiger Charakterbogen als druckbare HTML-Datei
    • Alle Attribute, Fertigkeiten, Talente, Ausrüstung
    • Zauber und Alchemie (wenn vorhanden)

Noch zu implementieren (Character Screen)

  • Level-Up System: Stufenaufstieg mit Attributs-, Talent- und Fertigkeitenwahl

Equipment-Datenbank

  • 5.482 Items aus Pathfinder 2e importiert
  • Waffen mit Schaden, Schadentyp, Reichweite, Eigenschaften
  • Rüstungen mit RK, DEX-Cap, Penalties
  • Verbrauchsgüter und allgemeine Ausrüstung
  • Durchsuchbar nach Name, Kategorie, Level, Eigenschaften
  • API-Endpunkte: /equipment, /equipment/categories, /equipment/weapons, etc.

Design-Prinzipien

  • Mobile-First: Touch-optimiert mit 44px+ Touch-Targets
  • Dark Mode: Primärfarbe #c26dbc (Magenta)
  • Deutsch: Alle UI-Texte auf Deutsch
  • Keine Emojis: Nur Lucide Icons

Environment-Variablen

Server (server/.env)

PORT=5000                    # Server-Port
DATABASE_URL="postgresql://..." # PostgreSQL Connection String
JWT_SECRET="..."             # JWT Signing Key
ANTHROPIC_API_KEY="..."      # Claude API für Übersetzungen

Client (client/.env)

VITE_API_URL=http://localhost:5000/api  # Muss mit Server PORT übereinstimmen

Wichtig: Die WebSocket-URL wird automatisch aus VITE_API_URL abgeleitet (ohne /api Suffix).

Beispiel-Dateien: server/.env.example und client/.env.example

Entwicklung

# Backend starten (Port 5000, konfigurierbar via PORT in .env)
cd server && npm run start:dev

# Frontend starten (Port 5173)
cd client && npm run dev

# Prisma Migrations (IMMER Migrations verwenden, NIEMALS db push!)
cd server && npm run db:migrate:dev      # Neue Migration erstellen & anwenden
cd server && npm run db:migrate:deploy   # Migrations in Produktion anwenden
cd server && npm run db:migrate:status   # Status der Migrations prüfen
cd server && npm run db:migrate:reset    # DB zurücksetzen (Dev only!)

# Prisma Sonstiges
cd server && npm run db:studio           # DB Browser
cd server && npm run db:generate         # Prisma Client generieren
cd server && npm run db:seed             # Basis-Seed-Daten laden
cd server && npm run db:seed:equipment   # Equipment-Datenbank laden

Project

Dimension47

Dimension47 ist eine selbst gehostete Web-App für Pathfinder-2e-Tischrunden auf Deutsch. Sie verwaltet Kampagnen, Charakterbögen mit komplettem PF2e-Regelumfang (HP, Zustände, Inventar, Talente, Aktionen, Alchemie) und stellt einen GM-Battle-Screen mit 3D-Druck-Tisch-Display bereit — alles in Echtzeit synchronisiert. Zielgruppe ist die eigene Spielgruppe, nicht die breite Öffentlichkeit.

Core Value: Am Tisch funktioniert alles in Echtzeit und regelkonform: Spieler lesen ihren Charakterbogen am Handy, der GM steuert vom Laptop aus den Battle-Screen, der eingelassene Tisch-Display zeigt die Spielsicht — ohne Reibung, ohne falsche Werte, ohne Reload.

Constraints

  • Tech-Stack: NestJS 11 + React 19 + Prisma 7 + PostgreSQL + Socket.io + Tailwind v4 — gesetzt durch Bestand, kein Stack-Wechsel sinnvoll
  • Sprache: Deutsche UI durchgehend — alle neuen Texte ebenfalls Deutsch
  • Design: Mobile-First für alle nutzerseitigen Screens (Charakterbogen, Vault-Browser, Würfler, Chat); Battle-GM-Screen darf desktop-fokussiert bleiben; Tisch-Display ist eigener Layout-Modus
  • Daten-Persistenz: Alle PF2e-Daten gehören in die DB (Prisma-Seeds aus JSON), nichts wird zur Laufzeit aus JSON-Dateien gelesen
  • Migrationen: Schema-Änderungen ausschließlich über prisma migrate dev, niemals db push
  • Code-Qualität: TypeScript strict, keine any-Types, kein Quick-Fix der später wehtut
  • Hosting-Modell: Self-hosted für eigene Spielgruppe — keine Multi-Tenant-/SaaS-Anforderungen
  • Push-Plattform: Web Push (Service-Worker-basiert), kein FCM/APNs-Native-Wrapper
  • Vault-Endpoint: Selbst-gehosteter Endpoint (vermutlich auf eigenem Server) — konkretes Protokoll wird in der Vault-Phase entschieden, nicht jetzt

Technology Stack

Languages

  • TypeScript 5.9.3 (server), 5.7.3 (client) - Strict mode enabled, full type safety across codebase
  • JavaScript (build outputs, scripts)
  • HTML/CSS (frontend templates)

Runtime

  • Node.js (version not pinned, assumed LTS) - Used for both server and client dev/build
  • ES2023 target (server), ES2022 target (client)
  • npm - Lockfiles present for both client and server

Frameworks

  • React 19.2.0 - UI framework
  • React Router DOM 7.12.0 - Client-side routing
  • Vite 7.2.4 - Build tool and dev server
  • NestJS 11.0.1 - Web framework with TypeScript-first design
  • Express (via @nestjs/platform-express) - Underlying HTTP server
  • Tailwind CSS 4.1.18 - Utility-first CSS framework
  • @tailwindcss/vite plugin for Vite integration
  • Jest 30.0.0 - Test runner (server-side only, configured in package.json)
  • ts-jest - TypeScript support for Jest
  • Supertest 7.0.0 - HTTP assertion library (server integration tests)
  • @vitejs/plugin-react - React fast refresh for Vite

Key Dependencies

  • @prisma/client 7.2.0 - ORM and database abstraction layer
  • prisma 7.2.0 - CLI and schema management tool
  • @anthropic-ai/sdk 0.71.2 - Claude API for on-demand German translations
  • socket.io 4.8.3 - WebSocket library for real-time communication
  • @nestjs/websockets 11.1.12 - NestJS WebSocket integration
  • @nestjs/platform-socket.io 11.1.12 - Socket.io adapter for NestJS
  • @nestjs/jwt 11.0.2 - JWT authentication provider
  • @nestjs/passport 11.0.5 - Passport.js integration for authentication
  • passport-jwt 4.0.1 - JWT strategy for Passport
  • bcrypt 6.0.0 - Password hashing
  • class-validator 0.14.3 - Request DTO validation
  • class-transformer 0.5.1 - DTO transformation
  • @nestjs/swagger 11.2.5 - OpenAPI/Swagger documentation
  • @nestjs/config 4.0.2 - Environment configuration management
  • dotenv 17.2.3 - .env file loading
  • axios 1.13.2 - HTTP client library for API requests
  • socket.io-client 4.8.3 - WebSocket client for real-time updates
  • zustand 5.0.10 - Client state management (auth store)
  • @tanstack/react-query 5.90.19 - Server state and data fetching (caching, synchronization)
  • react-router-dom 7.12.0 - Client-side routing
  • framer-motion 12.26.2 - Animation library
  • lucide-react 0.562.0 - Icon library (SVG icons)
  • clsx 2.1.1 - Conditional CSS class utilities
  • tailwind-merge 3.4.0 - Tailwind class merging utility
  • @nestjs/cli 11.0.0 - NestJS code generation and project scaffolding
  • @nestjs/schematics 11.0.0 - Code generators for NestJS
  • prettier 3.4.2 - Code formatter
  • eslint 9.18.0 - Linting
  • typescript-eslint 8.20.0 - TypeScript ESLint support
  • tsx 4.21.0 - TypeScript execution (used for seed scripts)
  • tsconfig-paths 4.2.0 - TypeScript path alias resolution
  • ts-node 10.9.2 - TypeScript REPL and script runner
  • ts-loader 9.5.2 - TypeScript webpack loader
  • eslint 9.39.1 - Linting
  • typescript-eslint 8.46.4 - TypeScript ESLint support
  • eslint-plugin-react-hooks 7.0.1 - React Hooks linting rules
  • eslint-plugin-react-refresh 0.4.24 - Vite React refresh linting

Configuration

  • Server loads from .env file (see .env.example):
  • Client loads from .env or .env.local:
  • Server: server/tsconfig.json with target ES2023, decorators enabled
  • Client: client/tsconfig.app.json with target ES2022, strict mode
  • Client Vite config: client/vite.config.ts
  • Server NestJS config: server/nest-cli.json (if exists)

Platform Requirements

  • Node.js LTS (tested with v22)
  • npm (lockfiles version management)
  • PostgreSQL 16+ (via Docker Compose)
  • Docker & Docker Compose (for database)
  • Git
  • Node.js LTS
  • PostgreSQL 16+ (managed service or self-hosted)
  • Anthropic API key for translations (optional but recommended)
  • File storage: Local filesystem or cloud storage (currently local via ./uploads)

Database

  • Port 5432 (internal), 5433 (exposed for dev)
  • Database name: dimension47
  • Default credentials in docker-compose (dev only)
  • pgAdmin 4 included for database management (port 5050)
  • Schema: server/prisma/schema.prisma
  • Generator: Prisma Client with CommonJS module format
  • Adapter: @prisma/adapter-pg for optimized PostgreSQL queries
  • Output: src/generated/prisma/

Conventions

Naming Patterns

  • Components: kebab-case (e.g., character-sheet-page.tsx, add-condition-modal.tsx, hp-control.tsx)
  • Utilities/Services: kebab-case (e.g., use-character-socket.ts, export-character-html.ts)
  • Directories: kebab-case (e.g., features/, shared/, components/)
  • camelCase for all function names
  • Hooks prefixed with use (e.g., useAuthStore, useCharacterSocket, useMemo, useState)
  • Event handlers prefixed with handle (e.g., handleApply, handleConnection, handleDisconnect)
  • Getter/setter methods follow camelCase (e.g., getToken(), setToken())
  • camelCase for all variable names
  • Constants in UPPER_SNAKE_CASE (e.g., PROFICIENCY_BONUS, SKILL_DATA, TABS)
  • Type unions with capitalized names (e.g., CharacterType, AbilityType, TabType)
  • Boolean prefixes: is, has, should, can (e.g., isLoading, isOwner, hasAccess)
  • PascalCase for all types, interfaces, and enums
  • Domain types in shared: Character, Campaign, User, CharacterItem, CharacterFeat
  • Props interfaces suffixed with Props (e.g., HpControlProps, AddConditionModalProps)
  • DTO interfaces suffixed with Dto (e.g., CreateCharacterDto, LoginDto, RegisterDto)
  • State types in Zustand: domain-specific (e.g., AuthState)

Code Style

  • Prettier configured in server/.prettierrc with:
  • Line length: implicit (Prettier default ~80 chars but allows overflow)
  • Indentation: 2 spaces
  • Client: ESLint 9 with flat config (eslint.config.js)
  • Server: ESLint 9 with flat config (eslint.config.mjs)
  • Strict Mode Enforced on client (client/tsconfig.app.json):
  • Server TypeScript (server/tsconfig.json):

Import Organization

  • Client: @/*./src/* (defined in vite.config.ts and tsconfig.app.json)
  • Server: No path alias configured; uses relative paths
  • Always use @/ prefix on client to avoid relative path hell
  • Barrel files used: features/*/index.ts, shared/components/ui/index.ts
  • Default exports on pages: export default App
  • Named exports for utilities, types, hooks: export { HpControl }, export const api = new ApiClient()

Error Handling

  • Use NestJS exception classes: NotFoundException, ForbiddenException, UnauthorizedException, ConflictException
  • Access checks before operations (e.g., checkCampaignAccess(), checkCharacterAccess() in characters.service.ts)
  • Return meaningful error messages: "Campaign not found", "No access to this campaign"
  • Prisma operations wrapped in try-catch only when necessary for data validation
  • JWT verification throws exceptions through guard: JwtAuthGuard handles 401s
  • Axios interceptors for request/response handling (in api.ts)
  • 401 errors trigger logout and redirect to /login (except auth endpoints)
  • Error state in components: isLoading, error, pendingChange states
  • Modal operations: try/catch with setIsLoading(false) in finally block
  • Error logging: console.error() for debugging, no silent failures
  • User feedback: Navigation on error (navigate()) or via error state
  • Token validation on connection (throws client.disconnect())
  • Logger for all connection/disconnection events
  • Errors logged but don't crash server

Logging

  • Server: NestJS Logger (in modules/gateways)
  • Client: console.error() for error debugging
  • Server logs connection events with user context
  • Client silently catches most errors, logs critical ones
  • No debug logging infrastructure in place

Comments

  • Constants with unclear meaning (e.g., PROFICIENCY_BONUS values, skill-to-ability mappings)
  • Complex calculations (e.g., HP percentage calculations)
  • Business logic that isn't immediately obvious (e.g., Pathfinder 2e rules)
  • NOT used for obvious code ("increment counter")
  • Minimal usage observed
  • API methods documented with Swagger decorators on server: @ApiOperation(), @ApiResponse()
  • No runtime JSDoc comments in source

Function Design

  • Modal components: 500-1700 lines (large, but feature-complete)
  • Service methods: 10-50 lines (concise, focused)
  • Utility functions: 5-20 lines
  • Interface-based: Pass objects instead of multiple params
  • Optional params with defaults: remember: boolean = false
  • Async functions return typed Promises: async getCharacter(): Promise<Character>
  • Component callbacks: callbacks are async promises (onHpChange: (newHp: number) => Promise<void>)
  • Services return full domain objects with relations included

Module Design

  • Components export as named: export function HpControl() { ... }
  • Utilities export as named: export const api = new ApiClient()
  • One export per file (generally)
  • Used in features: features/auth/index.ts re-exports useAuthStore, LoginPage, RegisterPage
  • Used for UI components: shared/components/ui/index.ts re-exports all buttons, cards, inputs
  • Reduces import complexity
  • NestJS @Injectable() decorator for services
  • Constructor injection: constructor(private prisma: PrismaService)
  • Circular dependencies resolved with @Inject(forwardRef()): seen in CharactersService

State Management

  • Single store pattern: create<AuthState>()
  • Persisted state with middleware: persist()
  • Partialize: stores only non-sensitive fields (user, isAuthenticated)
  • Actions as methods in store: login(), logout(), checkAuth()
  • Error state in store: error: string | null
  • No client state management needed
  • WebSocket gateway maintains connection map: connectedClients = new Map()

Design Tokens (UI)

  • Primary: Magenta #c26dbc (in Tailwind as primary-500, primary-600, etc.)
  • Secondary: Dark grays for dark mode (secondary-800, secondary-700)
  • Text: Primary (light), secondary (dimmer), tertiary (dimmest)
  • Background: Primary, secondary, tertiary layers
  • Error: Red (error-500, error-600)
  • Success: Green (green-500)
  • Warning: Yellow (yellow-500)
  • Font sizes: sm, base, lg (Tailwind defaults)
  • Weights: normal, medium (600), semibold
  • All UI text in German except code/technical terms
  • Lucide React exclusively (e.g., Heart, Swords, BookOpen, Package)
  • No emoji anywhere
  • Icon sizes: h-4 w-4 (standard), h-6 w-6 (large)
  • Minimum 44px (mobile-first, accessible)
  • Buttons: h-11 (44px), h-9 (36px for small), h-12 (48px for large)
  • Icon buttons: h-11 w-11 (44x44px)
  • Tailwind v4 defaults: p-4, gap-2, rounded-lg, rounded-2xl
  • Modals: rounded-t-2xl sm:rounded-2xl (bottom sheet on mobile, centered on desktop)
  • Mobile-first breakpoints: sm: prefix for tablet+ (e.g., sm:items-center, sm:rounded-2xl)
  • Flexbox for layouts: flex, flex-col, items-center, justify-between
  • Grid rarely used

Architecture

Pattern Overview

  • Modular NestJS architecture with feature-based modules (Auth, Characters, Campaigns, Equipment, Battle)
  • Feature-first React organization with shared components and hooks
  • WebSocket Gateway real-time sync for character and battle state
  • Role-based access control (ADMIN, GM, PLAYER) enforced globally
  • Prisma ORM for PostgreSQL data persistence
  • JWT-based stateless authentication

Layers

  • Purpose: HTTP request handling and routing
  • Location: server/src/modules/*/[feature].controller.ts
  • Contains: REST endpoints with decorators (@Post, @Get, @Put, @Patch, @Delete)
  • Depends on: Services, DTOs, Guards, Decorators
  • Used by: HTTP clients (React frontend)
  • Examples:
  • Purpose: Business logic, data processing, validation
  • Location: server/src/modules/*/[feature].service.ts
  • Contains: Methods for creating, updating, deleting entities; complex calculations
  • Depends on: PrismaService, other Services, external APIs (Claude)
  • Used by: Controllers, Gateways, other Services
  • Examples:
  • Purpose: Real-time bidirectional communication for live updates
  • Location: server/src/modules/*/[feature].gateway.ts
  • Contains: Socket.io event handlers, authentication, room management
  • Depends on: JwtService, PrismaService, Services
  • Used by: React WebSocket hooks
  • Examples:
  • Purpose: Database abstraction and ORM
  • Location: server/src/prisma/prisma.service.ts
  • Contains: Prisma client wrapper, query interface
  • Depends on: PostgreSQL database
  • Used by: All Services
  • Data Models defined in: server/prisma/schema.prisma
  • Purpose: Isolated feature domains with components, hooks, types
  • Location: client/src/features/[feature]/
  • Contains: Components, hooks, index.ts barrel exports
  • Examples:
  • Purpose: Reusable components, hooks, utilities, types across features
  • Location: client/src/shared/
  • Contains:
  • Used by: All features
  • Purpose: Navigation and route protection
  • Location: client/src/App.tsx
  • Contains: React Router v6 routes, protected route wrapper
  • Depends on: React Router, Feature components
  • Entry point: client/src/main.tsx
  • Purpose: Client-side state persistence
  • Location: client/src/features/auth/hooks/use-auth-store.ts
  • Contains: Zustand store for authentication state
  • Used by: Auth-related components, ProtectedRoute

Data Flow

Character Update (Real-Time WebSocket Sync)

Character Creation (Pathbuilder Import)

Battle Session Synchronization

Alchemy System State

Key Abstractions

  • Purpose: Database abstraction, query builder
  • Location: server/src/prisma/prisma.service.ts
  • Pattern: Singleton service injected into all modules
  • Used for: All CRUD operations, complex queries with relations
  • Purpose: Authentication and authorization
  • Location:
  • Pattern: NestJS guards executed globally on every request
  • Metadata: @Roles() and @Public() decorators control per-endpoint behavior
  • Purpose: HTTP communication abstraction
  • Location: client/src/shared/lib/api.ts
  • Pattern: Singleton class with axios instance
  • Features: Token management, auto-retry, auth interceptors, 401 handling
  • Purpose: Prevent duplicate connections, manage subscriptions
  • Location: client/src/shared/hooks/use-character-socket.ts
  • Pattern: Global socket singleton with ref counting
  • Features: Auto-reconnect, polling fallback, room subscription
  • Purpose: Type-safe event dispatch
  • Location:
  • Pattern: Union types for event kind discrimination

Entry Points

  • Location: server/src/main.ts
  • Triggers: npm run start:dev or deployed container startup
  • Responsibilities:
  • Location: client/src/main.tsx
  • Triggers: Browser page load or npm run dev
  • Responsibilities:
  • Location: client/src/App.tsx
  • Pattern: React Router v6 with protected routes
  • Flow:

Error Handling

  • NotFoundException - 404 when entity not found
  • ForbiddenException - 403 when user lacks permission
  • BadRequestException - 400 for invalid input
  • UnauthorizedException - 401 for auth failures
  • Global error filter could be added for consistent formatting
  • Service methods validate access before querying: checkCampaignAccess(), checkCharacterAccess()
  • API client response.interceptors catches 401 → redirects to /login
  • Components wrapped in error boundaries (future enhancement)
  • Failed requests return rejected promises to component
  • Token verification on connection → disconnect if invalid
  • No structured error responses; silent failures with console logging
  • Clients auto-reconnect via socket.io configuration

Cross-Cutting Concerns

  • Backend: NestJS Logger class used in services/gateways
  • Frontend: Console.log for development (socket.io events log connection state)
  • Backend: Global ValidationPipe with DTOs (class-validator)
  • Frontend: Form validation in components (manual checks in modals)
  • Prisma schema enforces constraints (NOT NULL, unique, enums)
  • Backend: JwtAuthGuard applied globally in app.module.ts
  • Endpoints opt-out via @Public() decorator
  • WebSocket: Token verified in gateway.handleConnection()
  • Frontend: Token stored in localStorage (persistent) or sessionStorage (session-only)
  • Backend: RolesGuard checks @Roles() metadata
  • Service methods verify campaign/character ownership before allowing operations
  • Pattern: Check campaign membership → check character ownership → allow operation
  • WebSocket Gateway manages rooms (one room per character/session)
  • Clients join room on component mount, leave on unmount
  • Broadcasts to all clients in room except sender (optional)

Project Skills

No project skills found. Add skills to any of: .claude/skills/, .agents/skills/, .cursor/skills/, or .github/skills/ with a SKILL.md index file.

GSD Workflow Enforcement

Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.

Use these entry points:

  • /gsd-quick for small fixes, doc updates, and ad-hoc tasks
  • /gsd-debug for investigation and bug fixing
  • /gsd-execute-phase for planned phase work

Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.

Developer Profile

Profile not yet configured. Run /gsd-profile-user to generate your developer profile. This section is managed by generate-claude-profile -- do not edit manually.