All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m44s
70 lines
3.7 KiB
Markdown
70 lines
3.7 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
pnpm dev # Start dev server
|
|
pnpm build # Production build
|
|
pnpm lint # ESLint
|
|
pnpm typecheck # tsc --noEmit
|
|
|
|
pnpm test # Vitest unit tests (run once)
|
|
pnpm test:e2e # Playwright E2E (requires dev server running)
|
|
|
|
pnpm db:generate # Regenerate Prisma client after schema changes
|
|
pnpm db:push # Sync schema to DB (dev, no migration files)
|
|
pnpm db:migrate # Apply migrations (production)
|
|
pnpm db:seed # Seed with sample data
|
|
pnpm db:studio # Open Prisma Studio
|
|
```
|
|
|
|
Package manager: **pnpm**.
|
|
|
|
## Coding conventions
|
|
|
|
### Server-first by default
|
|
This codebase maximises server-side rendering and minimises client-side JavaScript:
|
|
|
|
- **All pages are server components** by default. Never add `"use client"` to a page file.
|
|
- **Data fetching always happens server-side** in `src/lib/server-data.ts` — never `fetch()` from the client, never call Prisma from a client component.
|
|
- **All mutations use server actions** (`src/actions/`) — never create new API routes for mutations. The only remaining API routes are the export endpoints and auth (see below).
|
|
- **`"use client"` is only added** to components that genuinely need browser APIs or React state (forms, interactive widgets). Keep the surface area small.
|
|
- **Auth checks happen in every server action** via `const session = await auth()` before touching the DB.
|
|
|
|
### Data flow pattern
|
|
- **Server page** calls `src/lib/server-data.ts` functions (which call `auth()` + Prisma internally)
|
|
- Page passes serialized data as props to **client components** in `src/components/`
|
|
- Client components call **server actions** (`src/actions/`) for mutations
|
|
- Server actions call `revalidatePath()` to trigger cache invalidation
|
|
|
|
### Auth
|
|
`src/auth.ts` — NextAuth v5 with Credentials provider (email + bcrypt password). JWT strategy with `id` and `role` added to the token. Two roles: `evaluator` (default) and `admin`.
|
|
|
|
`src/middleware.ts` — Protects all routes. Admin routes redirect non-admins. Auth routes redirect logged-in users to `/dashboard`.
|
|
|
|
### Access control
|
|
`src/lib/evaluation-access.ts` — `canAccessEvaluation()` is the single source of truth. An evaluation is accessible if: user is admin, user is the evaluator, evaluation is shared with the user (`EvaluationShare`), or `isPublic` is true (read-only).
|
|
|
|
### Database
|
|
SQLite in dev (`DATABASE_URL=file:./dev.db`), swap to Postgres for production. Schema lives in `prisma/schema.prisma`. Key relations:
|
|
- `Evaluation` → `Template` → `TemplateDimension[]`
|
|
- `Evaluation` → `DimensionScore[]` (one per dimension, `@@unique([evaluationId, dimensionId])`)
|
|
- `Evaluation` → `EvaluationShare[]` (many users)
|
|
- `Evaluation` → `AuditLog[]`
|
|
|
|
`TemplateDimension.suggestedQuestions` is stored as a JSON string (array). `TemplateDimension.rubric` is stored as a `"1:X;2:Y;..."` string. Both are parsed client-side.
|
|
|
|
### API routes (remaining)
|
|
Only exports and auth use API routes:
|
|
- `GET /api/export/csv?id=` and `GET /api/export/pdf?id=` — use `src/lib/export-utils.ts`
|
|
- `POST /api/ai/suggest-followups` — **stub**, returns deterministic suggestions; replace with real LLM call if needed
|
|
- `POST /api/auth/signup` — user registration
|
|
|
|
### Key types
|
|
`src/types/next-auth.d.ts` extends `Session.user` with `id` and `role`. Always use `session.user.id` (never `session.user.email`) as the user identifier in server actions.
|
|
|
|
### JWT staleness
|
|
`session.user.name` comes from the JWT token frozen at login time. If a page needs the user's current `name` (or any other mutable profile field), query Prisma directly using `session.user.id` — do not rely on the session object for those values.
|