# MOPC Platform - Claude Code Context ## Project Overview **MOPC (Monaco Ocean Protection Challenge)** is a secure jury online voting platform for managing project selection rounds. The platform enables jury members to evaluate submitted ocean conservation projects, with Phase 1 supporting two selection rounds: - **Round 1**: ~130 projects → ~60 semi-finalists - **Round 2**: ~60 projects → 6 finalists **Domain**: `monaco-opc.com` The platform is designed for future expansion into a comprehensive program management system including learning hub, communication workflows, and partner modules. ## Key Decisions | Decision | Choice | |----------|--------| | Evaluation Criteria | Fully configurable per round (admin defines) | | CSV Import | Flexible column mapping (admin maps columns) | | Max File Size | 500MB (for videos) | | Observer Role | Included in Phase 1 | | First Admin | Database seed script | | Past Evaluations | Visible read-only after submit | | Grace Period | Admin-configurable per juror/project | | Smart Assignment | AI-powered (GPT) + Smart Algorithm fallback + geo-diversity, familiarity, COI scoring | | AI Data Privacy | All data anonymized before sending to GPT | | Evaluation Criteria Types | `numeric`, `text`, `boolean`, `section_header` (backward-compatible) | | COI Workflow | Mandatory declaration before evaluation, admin review | | Evaluation Reminders | Cron-based email reminders with countdown urgency | ## Brand Identity | Name | Hex | Usage | |------|-----|-------| | Primary Red | `#de0f1e` | CTAs, alerts | | Dark Blue | `#053d57` | Headers, sidebar | | White | `#fefefe` | Backgrounds | | Teal | `#557f8c` | Links, secondary | **Typography**: Montserrat (600/700 for headings, 300/400 for body) ## Tech Stack | Layer | Technology | Version | |-------|-----------|---------| | **Framework** | Next.js (App Router) | 15.x | | **Language** | TypeScript | 5.x | | **UI Components** | shadcn/ui | latest | | **Styling** | Tailwind CSS | 3.x | | **API Layer** | tRPC | 11.x | | **Database** | PostgreSQL | 16.x | | **ORM** | Prisma | 6.x | | **Authentication** | NextAuth.js (Auth.js) | 5.x | | **AI** | OpenAI GPT | 4.x SDK | | **Animation** | Motion (Framer Motion) | 11.x | | **Notifications** | Sonner | 1.x | | **Command Palette** | cmdk | 1.x | | **File Storage** | MinIO (S3-compatible) | External | | **Email** | Nodemailer + Poste.io | External | | **Containerization** | Docker Compose | 2.x | | **Reverse Proxy** | Nginx | External | ## Architecture Principles 1. **Type Safety First**: End-to-end TypeScript from database to UI via Prisma → tRPC → React 2. **Mobile-First Responsive**: All components designed for mobile, enhanced for desktop 3. **Full Control**: No black-box services; every component is understood and maintainable 4. **Extensible Data Model**: JSON fields for future attributes without schema migrations 5. **Security by Default**: RBAC, audit logging, secure file access with pre-signed URLs ## File Structure ``` mopc-platform/ ├── CLAUDE.md # This file - project context ├── docs/ │ └── architecture/ # Architecture documentation │ ├── README.md # System overview │ ├── database.md # Database design │ ├── api.md # API design │ ├── infrastructure.md # Deployment docs │ └── ui.md # UI/UX patterns ├── src/ │ ├── app/ # Next.js App Router pages │ │ ├── (auth)/ # Public auth routes (login, verify) │ │ ├── (admin)/ # Admin dashboard (protected) │ │ ├── (jury)/ # Jury interface (protected) │ │ ├── api/ # API routes │ │ │ ├── trpc/ # tRPC endpoint │ │ │ └── cron/ │ │ │ └── reminders/ # Cron endpoint for evaluation reminders (F4) │ │ ├── layout.tsx # Root layout │ │ └── page.tsx # Home/landing │ ├── components/ │ │ ├── ui/ # shadcn/ui components │ │ ├── admin/ # Admin-specific components │ │ │ └── evaluation-summary-card.tsx # AI summary display │ │ ├── forms/ # Form components │ │ │ ├── evaluation-form.tsx # With progress indicator (F1) │ │ │ ├── coi-declaration-dialog.tsx # COI blocking dialog (F5) │ │ │ └── evaluation-form-with-coi.tsx # COI-gated wrapper (F5) │ │ ├── layouts/ # Layout components (sidebar, nav) │ │ └── shared/ # Shared components │ │ └── countdown-timer.tsx # Live countdown with urgency (F4) │ ├── lib/ │ │ ├── auth.ts # NextAuth configuration │ │ ├── prisma.ts # Prisma client singleton │ │ ├── trpc/ # tRPC client & server setup │ │ ├── minio.ts # MinIO client │ │ └── email.ts # Email utilities │ ├── server/ │ │ ├── routers/ # tRPC routers by domain │ │ │ ├── program.ts │ │ │ ├── round.ts │ │ │ ├── project.ts │ │ │ ├── user.ts │ │ │ ├── assignment.ts │ │ │ ├── evaluation.ts │ │ │ ├── audit.ts │ │ │ ├── settings.ts │ │ │ ├── gracePeriod.ts │ │ │ ├── export.ts # CSV export incl. filtering results (F2) │ │ │ ├── analytics.ts # Reports/analytics (observer access, F3) │ │ │ └── mentor.ts # Mentor messaging endpoints (F10) │ │ ├── services/ # Business logic services │ │ │ ├── smart-assignment.ts # With geo/familiarity/COI scoring (F8) │ │ │ ├── evaluation-reminders.ts # Email reminder service (F4) │ │ │ └── ai-evaluation-summary.ts # GPT summary generation (F7) │ │ └── middleware/ # RBAC & auth middleware │ ├── hooks/ # React hooks │ ├── types/ # Shared TypeScript types │ └── utils/ # Utility functions ├── prisma/ │ ├── schema.prisma # Database schema │ ├── migrations/ # Migration files │ └── seed.ts # Seed data ├── public/ # Static assets ├── docker/ │ ├── Dockerfile # Production build │ ├── docker-compose.yml # Production stack │ └── docker-compose.dev.yml # Development stack ├── tests/ │ ├── unit/ # Unit tests │ └── e2e/ # End-to-end tests └── config files... # package.json, tsconfig, etc. ``` ## Coding Standards ### TypeScript - Strict mode enabled - Explicit return types for functions - Use `type` over `interface` for consistency (unless extending) - Prefer `unknown` over `any` ### React/Next.js - Use Server Components by default - `'use client'` only when needed (interactivity, hooks) - Collocate components with their routes when specific to that route - Use React Query (via tRPC) for server state ### Naming Conventions - **Files**: kebab-case (`user-profile.tsx`) - **Components**: PascalCase (`UserProfile`) - **Functions/Variables**: camelCase (`getUserById`) - **Constants**: SCREAMING_SNAKE_CASE (`MAX_FILE_SIZE`) - **Database Tables**: PascalCase in Prisma (`User`, `Project`) - **Database Columns**: camelCase in Prisma (`createdAt`) ### Styling - Tailwind CSS utility classes - Mobile-first: base styles for mobile, `md:` for tablet, `lg:` for desktop - Use shadcn/ui components as base, customize via CSS variables - No inline styles; no separate CSS files unless absolutely necessary ### API Design (tRPC) - Group by domain: `trpc.program.create()`, `trpc.round.list()` - Use Zod for input validation - Return consistent response shapes - Throw `TRPCError` with appropriate codes ## Common Commands ```bash # Development npm run dev # Start Next.js dev server npm run db:studio # Open Prisma Studio npm run db:push # Push schema changes (dev only) npm run db:migrate # Run migrations npm run db:seed # Seed database # Testing npm run test # Run unit tests npm run test:e2e # Run E2E tests npm run test:coverage # Test with coverage # Build & Deploy npm run build # Production build npm run start # Start production server docker compose up -d # Start Docker stack docker compose logs -f app # View app logs # Code Quality npm run lint # ESLint npm run format # Prettier npm run typecheck # TypeScript check ``` ## Windows Development Notes **IMPORTANT**: On Windows, all Docker commands AND all npm/node commands must be run using PowerShell (`powershell -ExecutionPolicy Bypass -Command "..."`), not bash/cmd. This is required for proper Docker Desktop integration and Node.js execution. **IMPORTANT**: When invoking PowerShell from bash, always use `-ExecutionPolicy Bypass` to skip the user profile script which is blocked by execution policy: ```bash powershell -ExecutionPolicy Bypass -Command "..." ``` Examples: ```bash # npm commands powershell -ExecutionPolicy Bypass -Command "npm install" powershell -ExecutionPolicy Bypass -Command "npm run build" powershell -ExecutionPolicy Bypass -Command "npx prisma generate" # Docker commands powershell -ExecutionPolicy Bypass -Command "docker compose -f docker/docker-compose.dev.yml up -d" ``` ```powershell # Docker commands on Windows (use PowerShell) docker compose -f docker/docker-compose.dev.yml up -d docker compose -f docker/docker-compose.dev.yml build --no-cache app docker compose -f docker/docker-compose.dev.yml logs -f app docker compose -f docker/docker-compose.dev.yml down ``` ## Environment Variables ```env # Database DATABASE_URL="postgresql://user:pass@localhost:5432/mopc" # NextAuth NEXTAUTH_URL="https://monaco-opc.com" NEXTAUTH_SECRET="your-secret-key" # MinIO (existing separate stack) MINIO_ENDPOINT="http://localhost:9000" MINIO_ACCESS_KEY="your-access-key" MINIO_SECRET_KEY="your-secret-key" MINIO_BUCKET="mopc-files" # Email (Poste.io - existing) SMTP_HOST="localhost" SMTP_PORT="587" SMTP_USER="noreply@monaco-opc.com" SMTP_PASS="your-smtp-password" EMAIL_FROM="MOPC Platform " # OpenAI (for smart assignment and AI evaluation summaries) OPENAI_API_KEY="your-openai-api-key" # Cron (for scheduled evaluation reminders) CRON_SECRET="your-cron-secret-key" ``` ## Key Architectural Decisions ### 1. Next.js App Router over Pages Router **Rationale**: Server Components reduce client bundle, better data fetching patterns, layouts system ### 2. tRPC over REST **Rationale**: End-to-end type safety without code generation, excellent DX with autocomplete ### 3. Prisma over raw SQL **Rationale**: Type-safe queries, migration system, works seamlessly with TypeScript ### 4. NextAuth.js over custom auth **Rationale**: Battle-tested, supports magic links, session management built-in ### 5. MinIO (external) over local file storage **Rationale**: S3-compatible, pre-signed URLs for security, scalable, already deployed ### 6. JSON fields for extensibility **Rationale**: `metadata_json`, `settings_json` allow adding attributes without migrations ### 7. Soft deletes with status fields **Rationale**: Audit trail preservation, recovery capability, referential integrity ## User Roles (RBAC) | Role | Permissions | |------|------------| | **SUPER_ADMIN** | Full system access, all programs, user management | | **PROGRAM_ADMIN** | Manage specific programs, rounds, projects, jury | | **JURY_MEMBER** | View assigned projects only, submit evaluations, declare COI | | **OBSERVER** | Read-only access to dashboards, all analytics/reports | | **MENTOR** | View assigned projects, message applicants via `mentorProcedure` | | **APPLICANT** | View own project status, upload documents per round, message mentor | ## Important Constraints 1. **Jury can only see assigned projects** - enforced at query level 2. **Voting windows are strict** - submissions blocked outside active window 3. **Evaluations are versioned** - edits create new versions 4. **All admin actions are audited** - immutable audit log 5. **Files accessed via pre-signed URLs** - no public bucket access 6. **Mobile responsiveness is mandatory** - every view must work on phones 7. **File downloads require project authorization** - jury/mentor must be assigned to the project 8. **Mentor endpoints require MENTOR role** - uses `mentorProcedure` middleware 9. **COI declaration required before evaluation** - blocking dialog gates evaluation form; admin reviews COI declarations 10. **Evaluation form supports multiple criterion types** - `numeric`, `text`, `boolean`, `section_header`; defaults to `numeric` for backward compatibility 11. **Smart assignment respects COI** - jurors with declared conflicts are skipped entirely; geo-diversity penalty and prior-round familiarity bonus applied 12. **Cron endpoints protected by CRON_SECRET** - `/api/cron/reminders` validates secret header 13. **Project status changes tracked** - every status update creates a `ProjectStatusHistory` record 14. **Per-round document management** - `ProjectFile` supports `roundId` scoping and `isLate` deadline tracking ## Security Notes ### CSRF Protection tRPC mutations are protected against CSRF attacks because: - tRPC uses `application/json` content type, which triggers CORS preflight on cross-origin requests - Browsers block cross-origin JSON POSTs by default (Same-Origin Policy) - NextAuth's own routes (`/api/auth/*`) have built-in CSRF token protection - No custom CORS headers are configured to allow external origins **Do NOT add permissive CORS headers** (e.g., `Access-Control-Allow-Origin: *`) without also implementing explicit CSRF token validation on all mutation endpoints. ### Rate Limiting - tRPC API: 100 requests/minute per IP - Auth endpoints: 10 POST requests/minute per IP - Account lockout: 5 failed password attempts triggers 15-minute lockout ## External Services (Pre-existing) These services are already running on the VPS in separate Docker Compose stacks: - **MinIO**: `http://localhost:9000` - S3-compatible storage - **Poste.io**: `localhost:587` - SMTP server for emails - **Nginx**: Host-level reverse proxy with SSL (certbot) The MOPC platform connects to these via environment variables. ## Phase 1 Scope ### In Scope - Round management (create, configure, activate/close) - Project import (CSV) and file uploads - Jury invitation (magic link) - Manual project assignment (single + bulk) - Evaluation form (configurable criteria) - Autosave + final submit - Voting window enforcement - Progress dashboards - CSV export - Audit logging - **F1: Evaluation progress indicator** - sticky status bar with percentage tracking across criteria, global score, decision, feedback - **F2: Export filtering results as CSV** - dynamic AI column flattening from `aiScreeningJson` - **F3: Observer access to reports/analytics** - all 8 analytics procedures use `observerProcedure`; observer reports page with round selector, tabs, charts - **F4: Countdown timer + email reminders** - live countdown with urgency colors; `EvaluationRemindersService` with cron endpoint (`/api/cron/reminders`) - **F5: Conflict of Interest declaration** - `ConflictOfInterest` model; blocking dialog before evaluation; admin COI review page - **F6: Bulk status update UI** - checkbox selection, floating toolbar, `ProjectStatusHistory` tracking - **F7: AI-powered evaluation summary** - `EvaluationSummary` model; GPT-generated strengths/weaknesses, themes, scoring stats - **F8: Smart assignment improvements** - `geoDiversityPenalty`, `previousRoundFamiliarity`, `coiPenalty` scoring factors - **F9: Evaluation form flexibility** - extended criterion types (`numeric`, `text`, `boolean`, `section_header`); conditional visibility, section grouping - **F10: Applicant portal enhancements** - `ProjectStatusHistory` timeline; per-round document management (`roundId` + `isLate` on `ProjectFile`); `MentorMessage` model for mentor-applicant chat ### Out of Scope (Phase 2+) - Typeform/Notion integrations - WhatsApp notifications - Learning hub - Partner modules - Public website ## Testing Strategy - **Unit Tests**: Business logic, utilities, validators - **Integration Tests**: tRPC routers with test database - **E2E Tests**: Critical user flows (Playwright) - **Manual Testing**: Responsive design on real devices ## Documentation Links - [Architecture Overview](./docs/architecture/README.md) - [Database Design](./docs/architecture/database.md) - [API Design](./docs/architecture/api.md) - [Infrastructure](./docs/architecture/infrastructure.md) - [UI/UX Patterns](./docs/architecture/ui.md)