chore: add root-level CLAUDE.md and docker-compose.yml
Monorepo root files for documentation and unified Docker Compose that brings up all three services (db, api, front, intra) together. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
123
CLAUDE.md
Normal file
123
CLAUDE.md
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
CrowMate Nest is a community platform for **Headless Hazard**, an indie game. It consists of three monorepo sub-projects:
|
||||||
|
|
||||||
|
- **`nest-backend/`**: REST API (Express + TypeScript + PostgreSQL/Prisma)
|
||||||
|
- **`nest-front/`**: Public-facing community website (React + Vite, port 5173)
|
||||||
|
- **`nest-intra/`**: Staff-only internal portal (React + Vite, port 5174)
|
||||||
|
|
||||||
|
## Development Commands
|
||||||
|
|
||||||
|
### Backend (`nest-backend/`)
|
||||||
|
```bash
|
||||||
|
npm run dev # ts-node-dev with auto-restart
|
||||||
|
npm run build # TypeScript compilation to dist/
|
||||||
|
npm start # Run compiled dist/index.js
|
||||||
|
npm run db:push # Push Prisma schema changes (no migration file)
|
||||||
|
npm run db:migrate # Create and apply a migration
|
||||||
|
npm run db:seed # Run prisma/seed.ts
|
||||||
|
npm run db:studio # Open Prisma Studio UI
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend & Intranet (`nest-front/` and `nest-intra/`)
|
||||||
|
```bash
|
||||||
|
npm run dev # Vite dev server
|
||||||
|
npm run build # tsc + vite build
|
||||||
|
npm run lint # ESLint
|
||||||
|
npm run preview # Serve built output locally
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Setup (Backend)
|
||||||
|
Copy `.env.example` to `.env`. Key variables:
|
||||||
|
```env
|
||||||
|
DATABASE_URL="postgresql://user:password@localhost:5432/nest_db"
|
||||||
|
JWT_SECRET="..."
|
||||||
|
PORT=3000
|
||||||
|
ADMIN_USERNAME / ADMIN_EMAIL / ADMIN_PASSWORD # Auto-creates admin on startup
|
||||||
|
FRONT_ORIGIN / INTRA_ORIGIN # Production CORS origins
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
**Tech**: Express 4, TypeScript 5.6, Prisma 5.22, PostgreSQL, JWT (7d), bcryptjs, Zod
|
||||||
|
|
||||||
|
**Request pipeline**: `authenticate()` → `requireStaff()` / `requireAdmin()` middleware, then route handler. JWT payload includes `{ userId, role, isAdmin }`.
|
||||||
|
|
||||||
|
**Route groups** (all under `/api/`):
|
||||||
|
- `auth`: login, register, /me
|
||||||
|
- `users`: CRUD + ban/unban (admin)
|
||||||
|
- `forum`: categories, threads (paginated), replies
|
||||||
|
- `bugs`: bug reports with uniqueCode (HH-XXXX), comments, internal notes, me-too voting
|
||||||
|
- `feed`: staff-only post feed
|
||||||
|
- `events`: announcements/updates/milestones/polls with voting
|
||||||
|
- `team`: team member profiles
|
||||||
|
|
||||||
|
**Key patterns**:
|
||||||
|
- All request bodies validated with Zod (`schema.safeParse()`)
|
||||||
|
- Response shaping via format helpers (`formatBug()`, `formatMember()`, etc.) in `src/lib/`
|
||||||
|
- Prisma eager-loads relations to avoid N+1
|
||||||
|
- Composite primary keys for `MeTooBug` (userId + bugReportId) and `PollVote` (userId + pollOptionId)
|
||||||
|
|
||||||
|
### Frontends (nest-front & nest-intra)
|
||||||
|
|
||||||
|
**Tech**: React 19, Vite 7, Tailwind CSS 4, React Router 6, TypeScript 5.9
|
||||||
|
|
||||||
|
Both frontends currently use **mock data** — no real API calls are wired up yet. Auth state is simulated with `MOCK_USERS` in `src/contexts/AuthContext.tsx` and persisted to `localStorage`.
|
||||||
|
|
||||||
|
- `nest-front` uses storage key `crowmate_auth_user`; all roles (`user`, `dev`, `com`) can log in
|
||||||
|
- `nest-intra` uses storage key `crowmate_intra_user`; blocks `role === 'user'` at login — staff only (`dev` / `com`)
|
||||||
|
|
||||||
|
**Shared structure** (both React projects mirror each other):
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
App.tsx # Route definitions, React.lazy() imports
|
||||||
|
contexts/
|
||||||
|
AuthContext.tsx # Auth state, role helpers, localStorage
|
||||||
|
components/
|
||||||
|
layout/ # Page wrapper with nav/sidebar
|
||||||
|
shared/ # ProtectedRoute, PageLoader, DevRoleSwitcher
|
||||||
|
pages/ # Page components (lazy loaded)
|
||||||
|
types/index.ts # All TypeScript interfaces
|
||||||
|
utils/format.ts # formatDate(), timeAgo(), truncate()
|
||||||
|
data/mockData.ts # Mock users, forum, bugs, events, team
|
||||||
|
```
|
||||||
|
|
||||||
|
**DevRoleSwitcher component** (nest-front only): floating UI to switch auth roles instantly without logging out — for development testing only.
|
||||||
|
|
||||||
|
### User Roles & Access
|
||||||
|
|
||||||
|
| Role | Access |
|
||||||
|
|------|--------|
|
||||||
|
| `user` | Public site features only |
|
||||||
|
| `dev` / `com` | Staff features (feed, intranet, bug triage, event creation) |
|
||||||
|
| `isAdmin: true` | User management, forum moderation, destructive operations |
|
||||||
|
|
||||||
|
### Data Models Summary
|
||||||
|
|
||||||
|
**User**: id, username, email, password (hashed), role, isAdmin, isBanned, avatarUrl
|
||||||
|
|
||||||
|
**Forum**: ForumCategory → ForumThread → ForumReply (cascade deletes on thread)
|
||||||
|
|
||||||
|
**BugReport**: uniqueCode (HH-XXXX auto-generated), severity, status, assignedTo; with BugComment (public), BugReportNote (staff-only), MeTooBug
|
||||||
|
|
||||||
|
**Events**: EventPost (type: announcement | update | milestone | poll) → Poll → PollOption → PollVote (composite key)
|
||||||
|
|
||||||
|
**Team**: TeamMember standalone profiles
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
Each sub-project has its own `Dockerfile` and `docker-compose.yml`. The backend uses multi-stage builds; frontends use Nginx to serve the Vite build output (`nginx.conf` included).
|
||||||
|
|
||||||
|
## Key Implementation Notes
|
||||||
|
|
||||||
|
- The backend auto-creates an admin user on startup if `ADMIN_USERNAME/EMAIL/PASSWORD` env vars are set
|
||||||
|
- `prisma/seed.ts` populates sample data for development
|
||||||
|
- `nest-intra/public/services.json` defines quick-link cards for dev tools (GitHub, Plane, Jenkins, Proxmox, etc.) shown on the `/intranet/services` page
|
||||||
|
- Both frontends' `types/index.ts` and `utils/format.ts` are near-identical — changes often need to be mirrored
|
||||||
|
- When integrating real API calls, replace mock auth in `contexts/AuthContext.tsx` and mock data in `data/mockData.ts`
|
||||||
50
docker-compose.yml
Normal file
50
docker-compose.yml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: nest_db
|
||||||
|
POSTGRES_USER: nest_user
|
||||||
|
POSTGRES_PASSWORD: nest_password
|
||||||
|
volumes:
|
||||||
|
- db_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U nest_user -d nest_db"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
api:
|
||||||
|
build: ./nest-backend
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: postgresql://nest_user:nest_password@db:5432/nest_db
|
||||||
|
JWT_SECRET: ${JWT_SECRET:-change_me_in_production}
|
||||||
|
PORT: 3000
|
||||||
|
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
|
||||||
|
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@crowmate.fr}
|
||||||
|
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-change_me}
|
||||||
|
FRONT_ORIGIN: ${FRONT_ORIGIN:-http://localhost:5173}
|
||||||
|
INTRA_ORIGIN: ${INTRA_ORIGIN:-http://localhost:5174}
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
command: >
|
||||||
|
sh -c "npx prisma db push && node dist/index.js"
|
||||||
|
|
||||||
|
front:
|
||||||
|
build: ./nest-front
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "5173:5173"
|
||||||
|
|
||||||
|
intra:
|
||||||
|
build: ./nest-intra
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "5174:5174"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db_data:
|
||||||
Reference in New Issue
Block a user