MOPC Platform - Architecture Overview
System Overview
The MOPC Platform is a secure jury voting system built as a modern full-stack TypeScript application for the Monaco Ocean Protection Challenge. It follows a layered architecture with clear separation of concerns.
Phase 1 Focus: Jury selection rounds (130→60→6 projects)
Domain: monaco-opc.com
Finalized Decisions
| Decision |
Choice |
| Domain |
monaco-opc.com |
| 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 Provider |
Admin-configurable (OpenAI GPT) |
| AI Data Privacy |
All data anonymized/encoded before sending to GPT |
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 |
| File Storage |
MinIO (S3-compatible) |
External |
| Email |
Nodemailer + Poste.io |
External |
| Animation |
Motion (Framer Motion) |
11.x |
| Notifications |
Sonner |
1.x |
| Command Palette |
cmdk |
1.x |
| Containerization |
Docker Compose |
2.x |
| Reverse Proxy |
Nginx |
External |
Brand Identity
Colors
| Name |
Hex |
Usage |
| Primary Red |
#de0f1e |
Accents, CTAs, alerts |
| Dark Blue |
#053d57 |
Headers, sidebar, primary text |
| White |
#fefefe |
Backgrounds |
| Teal |
#557f8c |
Secondary elements, links |
Typography
- Headings: Montserrat (600/700 weight)
- Body: Montserrat Light (300/400 weight)
High-Level Architecture Diagram
┌─────────────────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Admin Views │ │ Jury Views │ │ Auth Views │ │
│ │ │ │ │ │ │ │
│ │ - Dashboard │ │ - Project List │ │ - Login │ │
│ │ - Rounds │ │ - Project View │ │ - Magic Link │ │
│ │ - Projects │ │ - Evaluation │ │ - Verify │ │
│ │ - Jury Mgmt │ │ - My Progress │ │ │ │
│ │ - Assignments │ │ │ │ │ │
│ │ - Reports │ │ │ │ │ │
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
│ │
│ Built with: Next.js App Router + React Server Components + shadcn/ui │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ API LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ tRPC Router │ │
│ │ │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │program │ │ round │ │project │ │ user │ │assign- │ │evalua- │ │ │
│ │ │Router │ │Router │ │Router │ │Router │ │ment │ │tion │ │ │
│ │ │ │ │ │ │ │ │ │ │Router │ │Router │ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Auth Middleware │ │ RBAC Middleware │ │ Audit Logger │ │
│ │ (NextAuth.js) │ │ (role checks) │ │ (all actions) │ │
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SERVICE LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Program │ │ Round │ │ Assignment │ │ Evaluation │ │
│ │ Service │ │ Service │ │ Service │ │ Service │ │
│ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ File │ │ Email │ │ Export │ │ Audit │ │
│ │ Service │ │ Service │ │ Service │ │ Service │ │
│ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ DATA LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Prisma ORM │ │
│ │ │ │
│ │ Type-safe database access, migrations, query building │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ PostgreSQL │ │ MinIO │ │
│ │ (Database) │ │ (File Store) │ │
│ │ │ │ │ │
│ │ - Users │ │ - PDFs │ │
│ │ - Programs │ │ - Videos │ │
│ │ - Rounds │ │ - Exports │ │
│ │ - Projects │ │ │ │
│ │ - Evaluations │ │ │ │
│ │ - Audit Logs │ │ │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Component Responsibilities
Presentation Layer
| Component |
Responsibility |
| Admin Views |
Program/round management, project import, jury management, assignments, dashboards |
| Jury Views |
View assigned projects, evaluate projects, track progress |
| Auth Views |
Login, magic link verification, session management |
| Layouts |
Responsive navigation, sidebar, mobile adaptations |
| UI Components |
shadcn/ui based, reusable, accessible |
API Layer
| Component |
Responsibility |
| tRPC Routers |
Type-safe API endpoints grouped by domain |
| Auth Middleware |
Session validation via NextAuth.js |
| RBAC Middleware |
Role-based access control enforcement |
| Audit Logger |
Record all significant actions |
| Validators |
Zod schemas for input validation |
Service Layer
| Service |
Responsibility |
| ProgramService |
CRUD for programs (e.g., "MOPC 2026") |
| RoundService |
Round lifecycle, voting windows, form versions |
| AssignmentService |
Jury-project assignments, load balancing |
| EvaluationService |
Form submission, autosave, scoring |
| FileService |
MinIO uploads, pre-signed URLs |
| EmailService |
Magic links, notifications via Nodemailer |
| ExportService |
CSV/Excel generation |
| AuditService |
Immutable event logging |
Data Layer
| Component |
Responsibility |
| Prisma Client |
Type-safe database queries |
| PostgreSQL |
Primary data store (relational) |
| MinIO |
S3-compatible file storage |
| Migrations |
Schema versioning and evolution |
Data Flow Examples
1. Jury Login Flow
User Next.js NextAuth PostgreSQL
│ │ │ │
│ 1. Enter email │ │ │
│───────────────────────>│ │ │
│ │ 2. Request magic link │ │
│ │───────────────────────>│ │
│ │ │ 3. Store token │
│ │ │───────────────────────>│
│ │ │<───────────────────────│
│ │ 4. Send email │ │
│ │<───────────────────────│ │
│ 5. Email with link │ │ │
│<───────────────────────│ │ │
│ │ │ │
│ 6. Click link │ │ │
│───────────────────────>│ │ │
│ │ 7. Verify token │ │
│ │───────────────────────>│ │
│ │ │ 8. Validate │
│ │ │───────────────────────>│
│ │ │<───────────────────────│
│ │ 9. Create session │ │
│ │<───────────────────────│ │
│ 10. Redirect to dash │ │ │
│<───────────────────────│ │ │
2. Jury Evaluation Flow
Jury Member Next.js/tRPC Service Layer PostgreSQL/MinIO
│ │ │ │
│ 1. View project list │ │ │
│───────────────────────>│ 2. project.listAssigned() │
│ │───────────────────────>│ 3. Query assignments │
│ │ │───────────────────────>│
│ │ │<───────────────────────│
│ 4. Show assigned projects │ │
│<───────────────────────│ │ │
│ │ │ │
│ 5. Open project │ │ │
│───────────────────────>│ 6. project.getDetails() │
│ │───────────────────────>│ 7. Get project + files│
│ │ │───────────────────────>│
│ │ │ 8. Generate pre-signed URLs
│ │ │<───────────────────────│
│ 9. Show project with file links │ │
│<───────────────────────│ │ │
│ │ │ │
│ 10. Fill evaluation │ │ │
│ (typing...) │ 11. evaluation.autosave() (debounced) │
│───────────────────────>│───────────────────────>│ 12. Save draft │
│ │ │───────────────────────>│
│ │ │<───────────────────────│
│ 13. Autosaved indicator │ │
│<───────────────────────│ │ │
│ │ │ │
│ 14. Submit final │ │ │
│───────────────────────>│ 15. evaluation.submit() │
│ │───────────────────────>│ 16. Validate window │
│ │ │ 17. Lock evaluation │
│ │ │ 18. Log audit event │
│ │ │───────────────────────>│
│ │ │<───────────────────────│
│ 19. Success, mark complete │ │
│<───────────────────────│ │ │
3. Admin Export Flow
Admin Next.js/tRPC Service Layer PostgreSQL/MinIO
│ │ │ │
│ 1. Request CSV export │ │ │
│───────────────────────>│ 2. export.generateCSV() │
│ │───────────────────────>│ 3. Query all evals │
│ │ │───────────────────────>│
│ │ │<───────────────────────│
│ │ │ 4. Build CSV │
│ │ │ 5. Upload to MinIO │
│ │ │───────────────────────>│
│ │ │<───────────────────────│
│ │ │ 6. Log audit event │
│ │ │───────────────────────>│
│ │ 7. Return download URL│ │
│ │<───────────────────────│ │
│ 8. Download file │ │ │
│<───────────────────────│ │ │
Security Architecture
Authentication
- Method: Email magic links (passwordless)
- Sessions: JWT stored in HTTP-only cookies
- Provider: NextAuth.js with custom email provider
Authorization (RBAC)
- Enforcement: tRPC middleware checks role before procedure
- Granularity: Role + resource-level (jury sees only assigned projects)
- Storage: User.role field in database
Data Security
- File Access: Pre-signed URLs with short TTL (15 min)
- SQL Injection: Prevented by Prisma parameterized queries
- XSS: React's built-in escaping + CSP headers
- CSRF: NextAuth.js built-in protection
Audit Trail
- Coverage: All admin actions, all state changes
- Immutability: Append-only audit_logs table
- Fields: user, action, entity, details, timestamp, IP
Scalability Considerations
Current Design (Phase 1)
- Single PostgreSQL instance (sufficient for ~200 concurrent users)
- Single Next.js instance behind Nginx
- MinIO for file storage (horizontally scalable)
Future Scale Path
- Database: Read replicas for dashboards, connection pooling (PgBouncer)
- Application: Multiple Next.js instances behind load balancer
- Caching: Redis for session storage and query caching
- CDN: Static assets via CDN
- Background Jobs: BullMQ for email queues, exports
Smart Assignment System
The platform includes two assignment modes:
1. AI-Powered Assignment (GPT)
- Analyzes juror expertise and project tags
- Optimizes for balanced workload
- Respects organizational conflicts
- Privacy: All data is anonymized before sending to GPT
- Names →
JUROR_A, JUROR_B
- Projects →
PROJECT_1, PROJECT_2
- Organizations →
ORG_X, ORG_Y
- Emails and personal details are never sent
2. Smart Algorithm (Rule-Based Fallback)
- Fully featured scoring algorithm
- No external API required
- Handles 200 projects × 50 jurors in < 1 second
- Deterministic results
Scoring Formula:
Score = (expertise_match × 40) + (load_balance × 25) +
(specialty_match × 20) + (diversity × 10) - (conflict × 100)
Admin Settings Panel
Centralized configuration for:
- AI Configuration: Provider, API key, model, budget limits
- Platform Branding: Logo, colors, name
- Email/SMTP: Server, credentials, templates
- File Storage: MinIO endpoint, bucket, limits
- Security: Session duration, rate limits
- Defaults: Timezone, pagination, autosave interval
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 |
Related Documentation