13 KiB
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 |
| Nodemailer + Poste.io | External | |
| Containerization | Docker Compose | 2.x |
| Reverse Proxy | Nginx | External |
Architecture Principles
- Type Safety First: End-to-end TypeScript from database to UI via Prisma → tRPC → React
- Mobile-First Responsive: All components designed for mobile, enhanced for desktop
- Full Control: No black-box services; every component is understood and maintainable
- Extensible Data Model: JSON fields for future attributes without schema migrations
- 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
typeoverinterfacefor consistency (unless extending) - Prefer
unknownoverany
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
TRPCErrorwith appropriate codes
Common Commands
# 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:
powershell -ExecutionPolicy Bypass -Command "..."
Examples:
# 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"
# 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
# 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 <noreply@monaco-opc.com>"
# 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
- Jury can only see assigned projects - enforced at query level
- Voting windows are strict - submissions blocked outside active window
- Evaluations are versioned - edits create new versions
- All admin actions are audited - immutable audit log
- Files accessed via pre-signed URLs - no public bucket access
- Mobile responsiveness is mandatory - every view must work on phones
- File downloads require project authorization - jury/mentor must be assigned to the project
- Mentor endpoints require MENTOR role - uses
mentorProceduremiddleware
Security Notes
CSRF Protection
tRPC mutations are protected against CSRF attacks because:
- tRPC uses
application/jsoncontent 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