# 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 | | AI Data Privacy | All data anonymized before sending to GPT | ## 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 │ │ ├── layout.tsx # Root layout │ │ └── page.tsx # Home/landing │ ├── components/ │ │ ├── ui/ # shadcn/ui components │ │ ├── forms/ # Form components (evaluation, etc.) │ │ ├── layouts/ # Layout components (sidebar, nav) │ │ └── shared/ # Shared components │ ├── 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 │ │ ├── services/ # Business logic services │ │ └── 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) OPENAI_API_KEY="your-openai-api-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 | | **OBSERVER** | Read-only access to dashboards (optional) | ## 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 ## 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 ### Out of Scope (Phase 2+) - Auto-assignment algorithm - 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)