193 lines
6.3 KiB
Markdown
193 lines
6.3 KiB
Markdown
# DnD Campaign Hub - Agent Guidelines
|
|
|
|
## Project Overview
|
|
|
|
Monorepo with a Node.js/Express API + Discord bot and React/Vite frontend.
|
|
|
|
**Stack:**
|
|
- Server: Node.js + TypeScript + Express + SQLite + Discord.js
|
|
- Web: React 19 + TypeScript + Vite + React Router
|
|
- Testing: Vitest
|
|
- Build: npm workspaces
|
|
|
|
## Commands
|
|
|
|
### Root (Monorepo)
|
|
```bash
|
|
npm install # Install all dependencies
|
|
npm run dev # Run both server and web in dev mode
|
|
npm run build # Build server and web
|
|
npm run test # Run all tests
|
|
```
|
|
|
|
### Server (`apps/server`)
|
|
```bash
|
|
npm run dev -w @dnd-hub/server # Dev mode with hot reload (tsx)
|
|
npm run build -w @dnd-hub/server # Compile TypeScript
|
|
npm run start -w @dnd-hub/server # Run compiled server
|
|
npm run test -w @dnd-hub/server # Run server tests
|
|
npm run migrate -w @dnd-hub/server # Run DB migrations
|
|
```
|
|
|
|
### Web (`apps/web`)
|
|
```bash
|
|
npm run dev -w @dnd-hub/web # Vite dev server (port 5173)
|
|
npm run build -w @dnd-hub/web # Type check + Vite build
|
|
npm run preview -w @dnd-hub/web # Preview production build
|
|
npm run test -w @dnd-hub/web # Run web tests
|
|
```
|
|
|
|
### Running a Single Test
|
|
```bash
|
|
# Run specific test file
|
|
npm run test -w @dnd-hub/server -- test/sessionService.test.ts
|
|
npm run test -w @dnd-hub/web -- src/smoke.test.ts
|
|
|
|
# Run with filter pattern
|
|
npm run test -w @dnd-hub/server -- --run --reporter=verbose
|
|
```
|
|
|
|
## Code Style
|
|
|
|
### TypeScript
|
|
- **Strict mode enabled** in both apps (`strict: true`)
|
|
- Target ES2022, use ESNext modules
|
|
- Server: `module: NodeNext`, `moduleResolution: NodeNext`
|
|
- Web: `module: ESNext`, `moduleResolution: Bundler`
|
|
- Always use `.ts`/`.tsx` extensions (no `.js` in src)
|
|
|
|
### Imports
|
|
- Use ES modules (`import`/`export`)
|
|
- Include `.js` extension for relative imports in server code
|
|
- Group imports: React/hooks first, then libraries, then local imports
|
|
- Example:
|
|
```typescript
|
|
import { useEffect, useState } from "react";
|
|
import { Link, Route, Routes } from "react-router-dom";
|
|
import { api } from "./api/client";
|
|
```
|
|
|
|
### Naming Conventions
|
|
- **Files**: camelCase for components/services (e.g., `CharacterSheetDrawer.tsx`, `sessionService.ts`)
|
|
- **Components**: PascalCase (e.g., `CharacterPage`, `ToastProvider`)
|
|
- **Functions/variables**: camelCase
|
|
- **Constants**: UPPER_SNAKE_CASE for config values
|
|
- **Types/Interfaces**: PascalCase (e.g., `Me`, `Campaign`)
|
|
- **Test files**: `*.test.ts` or `*.test.tsx` alongside or near tested code
|
|
|
|
### Formatting
|
|
- 2-space indentation
|
|
- Semicolons required
|
|
- Double quotes for strings (single in JSX when needed)
|
|
- Trailing commas in multi-line objects/arrays
|
|
- Max line length: ~100 chars (flexible)
|
|
|
|
### React Conventions
|
|
- Functional components with hooks only (no class components)
|
|
- Custom hooks prefixed with `use` (e.g., `useToast`, `useDebugMode`)
|
|
- Context providers for global state (Toast, Debug, CharacterSheet)
|
|
- Arrow functions for event handlers
|
|
- TypeScript interfaces for props
|
|
|
|
### Error Handling
|
|
- Server: Use try/catch with proper HTTP status codes
|
|
- Validate inputs with Zod schemas
|
|
- Web: Use Toast context for user-facing errors
|
|
- Log errors server-side, show friendly messages client-side
|
|
- Never expose stack traces to clients
|
|
|
|
### API Design
|
|
- RESTful endpoints under `/routes/`
|
|
- Use Express middleware for auth/validation
|
|
- CORS configured per environment
|
|
- Health check at `GET /health`
|
|
|
|
### Database
|
|
- SQLite via better-sqlite3 (synchronous)
|
|
- Migrations in `src/db/migrate.ts`
|
|
- Path: `./data/dnd_hub.db`
|
|
|
|
### Environment Variables
|
|
- Load via dotenv from monorepo root `.env`
|
|
- Use `config.ts` wrapper with defaults for dev
|
|
- Required vars throw on startup if missing
|
|
- Never commit `.env` (use `.env.example`)
|
|
|
|
### Testing
|
|
- Framework: Vitest
|
|
- Pattern: `describe`/`it`/`expect`
|
|
- Import from `vitest`
|
|
- Tests should be isolated and deterministic
|
|
- Smoke tests for basic functionality
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
dnd-hub/
|
|
├── apps/
|
|
│ ├── server/
|
|
│ │ ├── src/
|
|
│ │ │ ├── routes/ # Express route handlers
|
|
│ │ │ ├── services/ # Business logic
|
|
│ │ │ ├── db/ # Database schema/migrations
|
|
│ │ │ ├── discord/ # Discord bot commands
|
|
│ │ │ ├── jobs/ # Scheduled cron jobs
|
|
│ │ │ └── main.ts # Entry point
|
|
│ │ └── test/ # Test files
|
|
│ └── web/
|
|
│ ├── src/
|
|
│ │ ├── components/ # React components
|
|
│ │ ├── contexts/ # React context providers
|
|
│ │ ├── pages/ # Route page components
|
|
│ │ ├── api/ # API client
|
|
│ │ └── App.tsx # Root component
|
|
│ └── vite.config.ts
|
|
├── infra/ # Docker, nginx config
|
|
├── scripts/ # Utility scripts
|
|
├── .env.example # Environment template
|
|
└── package.json # Workspace root
|
|
```
|
|
|
|
## Key Features
|
|
|
|
### Transcript Sessions
|
|
- Discord commands: `/session start`, `/session stop`, `/session status`
|
|
- API endpoints: `POST /sessions/*`, `GET /sessions/:id/transcript`
|
|
- Cloud sync via `CLOUD_API_BASE_URL` with HMAC signatures
|
|
|
|
### Discord Integration
|
|
- OAuth2 authentication flow
|
|
- Role-based permissions (admin/dm/player)
|
|
- Game night notifications via node-cron
|
|
|
|
### Recap System
|
|
- Configurable providers: ollama (local) or claude (cloud)
|
|
- Set via `RECAP_MODE` or `RECAP_PROVIDERS` env vars
|
|
|
|
## Common Tasks
|
|
|
|
### Adding a New Route
|
|
1. Create handler in `apps/server/src/routes/`
|
|
2. Register in `app.ts`
|
|
3. Add TypeScript types if needed
|
|
|
|
### Adding a React Component
|
|
1. Create in `apps/web/src/components/`
|
|
2. Use TypeScript with typed props
|
|
3. Follow existing component patterns
|
|
|
|
### Database Changes
|
|
1. Update schema in `src/db/migrate.ts`
|
|
2. Run `npm run migrate -w @dnd-hub/server`
|
|
|
|
### Debug Mode
|
|
- Web app has debug toggle to simulate player role
|
|
- Controlled via DebugContext
|
|
|
|
## Gotchas
|
|
|
|
- `.env` is at monorepo root, loaded relative to workspace
|
|
- Server uses `.js` extensions in imports (NodeNext module resolution)
|
|
- Web uses JSX transform (`jsx: react-jsx`)
|
|
- Both apps share Vitest but run independently
|
|
- Clean up both `.js` and `.ts` files in web/src (legacy JS exists)
|