MOPC-App/CLAUDE.md

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
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

# 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

  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