Files
Dimension-47/CLAUDE.md

593 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`)
```bash
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`)
```bash
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
```bash
# 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
```
<!-- GSD:project-start source:PROJECT.md -->
## 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
<!-- GSD:project-end -->
<!-- GSD:stack-start source:codebase/STACK.md -->
## 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/`
<!-- GSD:stack-end -->
<!-- GSD:conventions-start source:CONVENTIONS.md -->
## 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
<!-- GSD:conventions-end -->
<!-- GSD:architecture-start source:ARCHITECTURE.md -->
## 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)
### Equipment Database Search
### 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)
<!-- GSD:architecture-end -->
<!-- GSD:skills-start source:skills/ -->
## 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:skills-end -->
<!-- GSD:workflow-start source:GSD defaults -->
## 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.
<!-- GSD:workflow-end -->
<!-- GSD:profile-start -->
## 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.
<!-- GSD:profile-end -->