# Codebase Structure **Analysis Date:** 2026-04-27 ## Directory Layout ``` dimension47/ ├── client/ # React 19 + Vite frontend │ ├── src/ │ │ ├── main.tsx # React root + DOM render │ │ ├── App.tsx # Router setup (BrowserRouter, Routes) │ │ ├── index.css # Global styles (Tailwind v4) │ │ ├── app/ # App configuration & routing │ │ ├── features/ # Feature modules (auth, characters, campaigns, etc.) │ │ │ ├── auth/ # Authentication (login, register, useAuthStore) │ │ │ │ ├── components/ │ │ │ │ │ ├── login-page.tsx │ │ │ │ │ └── register-page.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-auth-store.ts │ │ │ │ └── index.ts # Barrel export │ │ │ ├── characters/ # Character sheet & inventory │ │ │ │ ├── components/ # Modals, tabs, controls │ │ │ │ │ ├── character-sheet-page.tsx # Main tab container │ │ │ │ │ ├── actions-tab.tsx # PF2e actions list │ │ │ │ │ ├── alchemy-tab.tsx # Alchemy system │ │ │ │ │ ├── add-condition-modal.tsx # Add status effect │ │ │ │ │ ├── add-item-modal.tsx # Equipment search & add │ │ │ │ │ ├── add-feat-modal.tsx # Add talent │ │ │ │ │ ├── feat-detail-modal.tsx # Talent details │ │ │ │ │ ├── item-detail-modal.tsx # Equipment details │ │ │ │ │ ├── hp-control.tsx # HP management │ │ │ │ │ ├── rest-modal.tsx # Rest system │ │ │ │ │ ├── recovery-check-modal.tsx # Dying state recovery │ │ │ │ │ ├── dying-indicator.tsx # Dying condition display │ │ │ │ │ ├── import-character-modal.tsx # Pathbuilder import │ │ │ │ │ ├── create-character-modal.tsx # New character │ │ │ │ │ ├── edit-character-modal.tsx # Edit character info │ │ │ │ │ └── image-crop-modal.tsx # Avatar cropping │ │ │ │ ├── utils/ │ │ │ │ │ └── export-character-html.ts # Character sheet HTML export │ │ │ │ └── index.ts │ │ │ ├── campaigns/ # Campaign management │ │ │ │ ├── components/ │ │ │ │ │ ├── campaigns-page.tsx # Campaign list (home) │ │ │ │ │ ├── campaign-detail-page.tsx # Campaign overview │ │ │ │ │ ├── create-campaign-modal.tsx # New campaign │ │ │ │ │ ├── edit-campaign-modal.tsx # Edit campaign info │ │ │ │ │ └── add-member-modal.tsx # Add player to campaign │ │ │ │ └── index.ts │ │ │ ├── battle/ # Battle screen & real-time combat │ │ │ │ ├── components/ │ │ │ │ │ ├── battle-page.tsx # Main battle screen │ │ │ │ │ ├── battle-canvas.tsx # Map & token rendering │ │ │ │ │ ├── battle-session-list.tsx # Session selection │ │ │ │ │ └── token.tsx # Token component │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-battle-socket.ts # Battle WebSocket hook │ │ │ │ └── index.ts │ │ │ └── library/ # GM library (maps, combatants) │ │ │ ├── components/ │ │ │ │ ├── library-page.tsx # Maps & combatants list │ │ │ │ ├── upload-map-modal.tsx # Add battle map │ │ │ │ └── create-combatant-modal.tsx # Create NPC template │ │ │ └── index.ts │ │ ├── shared/ # Reusable code across features │ │ │ ├── components/ │ │ │ │ ├── layout.tsx # App wrapper (navbar, layout) │ │ │ │ ├── protected-route.tsx # Auth enforcement wrapper │ │ │ │ └── ui/ # shadcn/ui components │ │ │ │ ├── button.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── spinner.tsx │ │ │ │ ├── action-icon.tsx │ │ │ │ └── index.ts │ │ │ ├── hooks/ │ │ │ │ ├── use-character-socket.ts # Character real-time sync │ │ │ │ └── (battle hooks if added) │ │ │ ├── lib/ │ │ │ │ ├── api.ts # API client (axios + token mgmt) │ │ │ │ └── utils.ts # Utility functions │ │ │ └── types/ │ │ │ └── index.ts # All TypeScript interfaces & types │ │ └── assets/ # Images, fonts │ ├── public/ │ │ ├── data/ # JSON data files (equipment, etc.) │ │ └── icons/ # SVG/icon files │ ├── index.html # HTML template │ ├── vite.config.ts # Vite configuration │ ├── tsconfig.json # TypeScript configuration │ ├── tailwind.config.js # Tailwind CSS v4 config │ ├── postcss.config.js # PostCSS plugins │ ├── package.json │ └── dist/ # Build output (generated) │ ├── server/ # NestJS backend │ ├── src/ │ │ ├── main.ts # Server bootstrap & app setup │ │ ├── app.module.ts # Root NestJS module (imports all features) │ │ ├── common/ # Shared utilities across modules │ │ │ └── decorators/ │ │ │ ├── current-user.decorator.ts # Extract user from request │ │ │ ├── public.decorator.ts # Skip auth on endpoints │ │ │ ├── roles.decorator.ts # Specify required roles │ │ │ └── index.ts │ │ ├── prisma/ │ │ │ └── prisma.service.ts # Database service wrapper │ │ ├── modules/ # Feature modules (NestJS-style) │ │ │ ├── auth/ # Authentication & JWT │ │ │ │ ├── auth.controller.ts # POST /auth/login, /auth/register │ │ │ │ ├── auth.service.ts # User validation, JWT signing │ │ │ │ ├── auth.module.ts # Module exports & dependencies │ │ │ │ ├── guards/ │ │ │ │ │ ├── jwt-auth.guard.ts # JWT validation (global) │ │ │ │ │ └── roles.guard.ts # Role checking │ │ │ │ ├── strategies/ │ │ │ │ │ └── jwt.strategy.ts # Passport JWT strategy │ │ │ │ └── dto/ │ │ │ │ ├── login.dto.ts │ │ │ │ └── register.dto.ts │ │ │ ├── campaigns/ # Campaign management │ │ │ │ ├── campaigns.controller.ts # CRUD campaigns, member management │ │ │ │ ├── campaigns.service.ts # Campaign operations & access checks │ │ │ │ ├── campaigns.module.ts │ │ │ │ └── dto/ │ │ │ │ └── (campaign DTOs) │ │ │ ├── characters/ # Character system (core feature) │ │ │ │ ├── characters.controller.ts # Character CRUD, conditions, items, feats │ │ │ │ ├── characters.service.ts # Character logic, HP, conditions, inventory │ │ │ │ ├── characters.gateway.ts # WebSocket real-time sync │ │ │ │ ├── characters.module.ts │ │ │ │ ├── pathbuilder-import.service.ts # Pathbuilder JSON parsing │ │ │ │ ├── alchemy.controller.ts # Alchemy endpoints │ │ │ │ ├── alchemy.service.ts # Alchemy system logic │ │ │ │ └── dto/ │ │ │ │ └── (character, alchemy DTOs) │ │ │ ├── equipment/ # Equipment database │ │ │ │ ├── equipment.controller.ts # GET /equipment (search, categories) │ │ │ │ ├── equipment.service.ts # Equipment search & filtering │ │ │ │ ├── equipment.module.ts │ │ │ │ └── dto/ │ │ │ ├── feats/ # Feat database │ │ │ │ ├── feats.controller.ts # GET /feats (search) │ │ │ │ ├── feats.service.ts # Feat queries │ │ │ │ ├── feats.module.ts │ │ │ │ └── dto/ │ │ │ ├── battle/ # Battle system (maps, sessions, tokens) │ │ │ │ ├── battle.controller.ts # POST/GET /battles │ │ │ │ ├── battle.service.ts # Battle session logic │ │ │ │ ├── battle.gateway.ts # WebSocket battle updates │ │ │ │ ├── battle.module.ts │ │ │ │ ├── battle-maps.controller.ts # Battle map CRUD │ │ │ │ ├── battle-maps.service.ts │ │ │ │ ├── combatants.controller.ts # NPC/monster templates │ │ │ │ ├── combatants.service.ts │ │ │ │ └── dto/ │ │ │ ├── translations/ # German translations cache │ │ │ │ ├── translations.controller.ts # GET translations │ │ │ │ ├── translations.service.ts # Cache & Claude API calls │ │ │ │ ├── translations.module.ts │ │ │ │ └── dto/ │ │ │ └── claude/ # Claude API integration │ │ │ ├── claude.module.ts │ │ │ └── claude.service.ts # Claude API wrapper │ │ └── generated/ # Generated code (do not edit) │ │ └── prisma/ # Prisma client types & enums │ │ ├── client.ts │ │ ├── models.ts │ │ ├── enums.ts │ │ └── ... │ ├── prisma/ # Prisma ORM configuration │ │ ├── schema.prisma # Database schema (tables, relations, enums) │ │ ├── migrations/ # Versioned database migrations │ │ │ ├── 20260118162916_init/ │ │ │ ├── 20260118225853_add_equipment_detail_fields/ │ │ │ ├── 20260119083024_add_credits_to_character/ │ │ │ └── 20260119111209_add_item_custom_fields/ │ │ ├── seed.ts # Base seed script (users, etc.) │ │ └── data/ # JSON source data for seeding │ │ ├── equipment.json # 5,482 PF2e equipment items │ │ ├── feats.json # PF2e talents │ │ ├── spells.json # PF2e spells │ │ ├── actions.json # PF2e combat actions │ │ ├── conditions.json # PF2e conditions (Pathfinder 2e ruleset) │ │ └── ... │ ├── src/generated/ # Generated Prisma types │ ├── package.json │ ├── tsconfig.json │ ├── nest-cli.json │ └── dist/ # Build output (generated) │ ├── .planning/ # Phase planning documents │ └── codebase/ # Architecture analysis (this file) │ ├── ARCHITECTURE.md │ ├── STRUCTURE.md │ ├── STACK.md │ ├── INTEGRATIONS.md │ ├── CONVENTIONS.md │ ├── TESTING.md │ └── CONCERNS.md ├── docs/ # Documentation ├── .claude/ # Claude settings & instructions │ └── settings.local.json ├── package-lock.json # Lock file (top-level) └── CLAUDE.md # Project guidelines (Quality > Speed) ``` ## Directory Purposes ### Client Structure **`client/src/features/`** - Feature-based modules - Each feature is a semi-independent domain (auth, characters, campaigns, battle, library) - Contains components specific to that feature - Exports public API via barrel exports (`index.ts`) - Examples: AuthFeature manages login/register, CharactersFeature manages character sheet - Pattern: Feature-based organization allows independent testing and scaling **`client/src/shared/`** - Cross-feature reusables - `components/ui/` - shadcn/ui primitive components (Button, Card, Input, etc.) - `components/layout.tsx` - App wrapper with navbar - `components/protected-route.tsx` - Auth enforcement for routes - `hooks/` - Custom React hooks (useCharacterSocket, etc.) - `lib/api.ts` - HTTP client with token management - `lib/utils.ts` - Helper functions - `types/` - All TypeScript interfaces shared across app - Pattern: Single source of truth for types, no duplication **`client/public/`** - Static files - `data/` - JSON files (if any live here, but equipment comes from backend) - `icons/` - SVG icons used in UI ### Server Structure **`server/src/modules/`** - NestJS modules by feature - Each module is self-contained: controller → service → gateway - Module exports what other modules need via `exports: []` in decorator - Examples: - CharactersModule exports CharactersService, CharactersGateway for cross-module use - AuthModule exports AuthService, guards for other modules to use - Pattern: Module-based organization with explicit dependency injection **`server/src/common/`** - Shared utilities - Decorators: @CurrentUser, @Public, @Roles - Guards: Shared by all modules - Pattern: Cross-cutting concerns in one place **`server/prisma/`** - Database layer - `schema.prisma` - Single source of truth for data model - `migrations/` - Versioned schema changes (never use `db push`) - `seed.ts` - Initial data - `data/` - JSON source files for seed scripts - Pattern: Database-first approach, all data in DB not JSON files ## Key File Locations ### Entry Points **Backend:** - `server/src/main.ts` - Bootstrap NestJS app, enable pipes/guards/swagger - AppModule at `server/src/app.module.ts` - Wires all modules together **Frontend:** - `client/src/main.tsx` - React root render - Router at `client/src/App.tsx` - BrowserRouter with route protection ### Configuration **Environment:** - `server/.env` - PostgreSQL, JWT_SECRET, ANTHROPIC_API_KEY, CORS_ORIGINS - `client/.env` - VITE_API_URL (must match server PORT) - Example files: `server/.env.example`, `client/.env.example` **Build & Development:** - Backend: - `server/nest-cli.json` - NestJS CLI config - `server/tsconfig.json` - TypeScript settings - Frontend: - `client/vite.config.ts` - Vite bundler (alias paths with `@`) - `client/tsconfig.json` - TypeScript settings (strict mode) - `client/tailwind.config.js` - Tailwind v4 customization - `client/postcss.config.js` - CSS processing ### Core Logic **Character System:** - Service: `server/src/modules/characters/characters.service.ts` - HP, conditions, items - Gateway: `server/src/modules/characters/characters.gateway.ts` - Real-time sync - Import: `server/src/modules/characters/pathbuilder-import.service.ts` - Pathbuilder parsing - Alchemy: `server/src/modules/characters/alchemy.service.ts` - Alchemy logic - UI: `client/src/features/characters/components/character-sheet-page.tsx` - Main page **Battle System:** - Service: `server/src/modules/battle/battle.service.ts` - Sessions & tokens - Gateway: `server/src/modules/battle/battle.gateway.ts` - Real-time sync - Canvas: `client/src/features/battle/components/battle-canvas.tsx` - Map & tokens **Equipment Database:** - Service: `server/src/modules/equipment/equipment.service.ts` - Search & filtering - Controller: `server/src/modules/equipment/equipment.controller.ts` - Endpoints - UI: `client/src/features/characters/components/add-item-modal.tsx` - Search UI - Data: `server/prisma/data/equipment.json` - 5,482 items (seeded to DB) **Authentication:** - Service: `server/src/modules/auth/auth.service.ts` - Login/register/JWT - Guard: `server/src/modules/auth/guards/jwt-auth.guard.ts` - Applied globally - Store: `client/src/features/auth/hooks/use-auth-store.ts` - Client-side auth state - API: `client/src/shared/lib/api.ts` - Token persistence (localStorage vs sessionStorage) ### Testing **Backend:** - Test files: `server/src/**/*.spec.ts` (not yet created - opportunity) - Config: `server/jest.config.js` (if exists) **Frontend:** - Test files: `client/src/**/*.spec.tsx` (not yet created - opportunity) - Config: `client/vitest.config.ts` (if exists) or `client/jest.config.js` ## Naming Conventions ### Files **Component files (React):** - Pattern: kebab-case `.tsx` - Example: `character-sheet-page.tsx`, `add-item-modal.tsx`, `hp-control.tsx` - Convention: Lowercase with hyphens, `.tsx` for JSX **Service files (NestJS):** - Pattern: kebab-case `.ts` - Example: `characters.service.ts`, `pathbuilder-import.service.ts`, `alchemy.service.ts` - Convention: Feature name + responsibility (service/controller/gateway) **Guard/Strategy files:** - Pattern: kebab-case `.ts` - Example: `jwt-auth.guard.ts`, `jwt.strategy.ts` **DTO files:** - Pattern: kebab-case `.ts` inside `dto/` folder - Example: `login.dto.ts`, `register.dto.ts` **Module files:** - Pattern: Feature name + `.module.ts` - Example: `auth.module.ts`, `characters.module.ts` ### Directories **Feature directories:** - Pattern: kebab-case (lowercase with hyphens) - Example: `auth/`, `campaigns/`, `characters/`, `battle/`, `library/` - Structure: Each feature has `components/`, `hooks/`, `utils/`, `index.ts` **Shared directories:** - Pattern: Descriptive plural or functional names - Examples: `components/`, `hooks/`, `lib/`, `types/`, `decorators/`, `strategies/` **Module sub-directories:** - Pattern: `guards/`, `strategies/`, `dto/` (lowercase) - Convention: Consistent across all modules ## Where to Add New Code ### New Feature **Backend:** 1. Create `server/src/modules/[feature]/` directory 2. Create files: - `[feature].module.ts` - NestJS module, imports dependencies - `[feature].controller.ts` - HTTP endpoints - `[feature].service.ts` - Business logic - `[feature].gateway.ts` (optional) - WebSocket if real-time needed - `dto/` folder with DTOs 3. Import module in `server/src/app.module.ts` **Frontend:** 1. Create `client/src/features/[feature]/` directory 2. Create sub-folders: - `components/` - React components - `hooks/` - Custom hooks (if state needed) - `index.ts` - Barrel export 3. Add routes in `client/src/App.tsx` **Database (if adding entities):** 1. Add model to `server/prisma/schema.prisma` 2. Run: `cd server && npm run db:migrate:dev` 3. Name migration descriptively: "add_new_feature_table" 4. Seeds automatically regenerate Prisma client ### New Component/Module **React Component:** - Location: `client/src/features/[feature]/components/[name].tsx` - Pattern: Named export + default export - Import shared types from `client/src/shared/types/index.ts` - Use API client from `client/src/shared/lib/api.ts` **NestJS Service:** - Location: `server/src/modules/[feature]/[name].service.ts` - Pattern: @Injectable() class with public methods - Inject PrismaService via constructor - Keep business logic in service, HTTP concern in controller **WebSocket Gateway:** - Location: `server/src/modules/[feature]/[name].gateway.ts` - Pattern: @WebSocketGateway() @Injectable() class - Authenticate in handleConnection() - Emit broadcasts to rooms via socket.server.to(room).emit() ### Utilities **Shared Frontend Helpers:** - Location: `client/src/shared/lib/utils.ts` - Pattern: Exported functions (no classes) - Use for date formatting, type checks, calculations **Shared Backend Helpers:** - Location: `server/src/common/` (create subdirectory if needed) - Pattern: Injectable services or utility functions - Example: CommonService for shared operations ## Special Directories **`server/prisma/migrations/`** - Purpose: Version control for database schema - Generated: Auto-created by `npm run db:migrate:dev` - Committed: YES (must be in git for reproducible deployments) - Manual edits: Rarely needed, but can fix SQL if migration is broken - Pattern: Timestamp-prefixed folders with `.sql` files inside **`server/src/generated/`** - Purpose: Prisma-generated types and client - Generated: Auto-created by `npm run db:generate` - Committed: NO (regenerated on install) - Manual edits: DO NOT EDIT — regenerate instead **`client/public/data/`** - Purpose: Static JSON files (currently unused, equipment in DB) - Generated: NO (manually added if needed) - Committed: YES - Pattern: Only for truly static reference data **`server/dist/` and `client/dist/`** - Purpose: Compiled/bundled output - Generated: YES (`npm run build`) - Committed: NO (.gitignore) - Pattern: Build artifacts, environment-specific **`server/node_modules/` and `client/node_modules/`** - Purpose: Installed dependencies - Generated: YES (`npm install`) - Committed: NO (.gitignore) - Pattern: Use package-lock.json for reproducibility --- *Structure analysis: 2026-04-27*