# Codebase Structure

**Analysis Date:** 2026-02-26

## Directory Layout

```
MOPC/
├── prisma/                    # Database schema and migrations
│   ├── schema.prisma          # Single source of truth for all models
│   ├── seed.ts                # Seed script (imports from docs/CSV files)
│   └── migrations/            # Prisma migration history (auto-generated)
├── src/
│   ├── app/                   # Next.js App Router — all routes
│   │   ├── (admin)/           # Admin dashboard route group (SUPER_ADMIN, PROGRAM_ADMIN)
│   │   ├── (jury)/            # Jury evaluation route group (JURY_MEMBER)
│   │   ├── (applicant)/       # Applicant dashboard route group (APPLICANT)
│   │   ├── (mentor)/          # Mentor workspace route group (MENTOR)
│   │   ├── (observer)/        # Observer read-only route group (OBSERVER)
│   │   ├── (auth)/            # Public auth pages (login, verify, onboarding)
│   │   ├── (public)/          # Fully public pages (apply, vote, live-scores)
│   │   ├── (settings)/        # User settings (profile)
│   │   └── api/               # API routes (tRPC, auth, cron, SSE, files, health)
│   ├── components/            # React components organized by domain
│   │   ├── admin/             # Admin-specific components
│   │   ├── jury/              # Jury-specific components
│   │   ├── applicant/         # Applicant-specific components
│   │   ├── mentor/            # Mentor-specific components
│   │   ├── observer/          # Observer-specific components
│   │   ├── public/            # Public-facing components
│   │   ├── forms/             # Shared form components (apply wizard, COI dialog)
│   │   ├── charts/            # Chart/visualization components
│   │   ├── dashboard/         # Dashboard widgets
│   │   ├── layouts/           # Navigation layouts per role (sidebar, nav bars)
│   │   ├── shared/            # Reusable cross-domain components
│   │   └── ui/                # shadcn/ui primitives
│   ├── server/                # Server-only code
│   │   ├── routers/           # tRPC domain routers (44+ files)
│   │   │   └── _app.ts        # Root router composing all domains
│   │   ├── services/          # Business logic services
│   │   ├── utils/             # Server utilities (audit, ai-usage, image-upload)
│   │   ├── trpc.ts            # tRPC init, middleware, procedure types
│   │   └── context.ts         # tRPC context factory (session + prisma + IP)
│   ├── lib/                   # Shared libraries (client + server)
│   │   ├── trpc/              # tRPC client (client.ts), server caller (server.ts)
│   │   ├── storage/           # Storage provider abstraction (S3/local)
│   │   ├── whatsapp/          # WhatsApp notification client
│   │   ├── auth.ts            # NextAuth full configuration
│   │   ├── auth.config.ts     # Edge-compatible auth config (middleware)
│   │   ├── auth-redirect.ts   # requireRole() server helper
│   │   ├── prisma.ts          # Prisma singleton with connection pooling
│   │   ├── logger.ts          # Structured logger (tagged, level-aware)
│   │   ├── email.ts           # Nodemailer email sender
│   │   ├── minio.ts           # MinIO client initialization
│   │   ├── openai.ts          # OpenAI client initialization
│   │   ├── rate-limit.ts      # In-memory rate limiter
│   │   ├── feature-flags.ts   # DB-backed feature flags
│   │   ├── round-config.ts    # Round config helper utilities
│   │   ├── utils.ts           # General utilities (cn, formatters)
│   │   └── [others]           # countries, pdf-generator, typeform, notion, etc.
│   ├── types/                 # TypeScript type definitions
│   │   ├── competition.ts     # Composite types for Competition/Round domain
│   │   ├── competition-configs.ts  # Per-RoundType Zod schemas + inferred types
│   │   └── wizard-config.ts   # Application wizard configuration types
│   ├── hooks/                 # Custom React hooks
│   │   ├── use-debounce.ts
│   │   ├── use-live-voting-sse.ts  # SSE subscription for live voting
│   │   └── use-stage-live-sse.ts   # SSE subscription for live stage
│   └── contexts/              # React contexts
│       └── edition-context.tsx # Edition/Program selector context
├── tests/                     # Test files (Vitest)
│   ├── setup.ts               # Test setup (prisma client, helpers)
│   ├── helpers.ts             # Test factories (createTestUser, createTestCompetition, etc.)
│   └── unit/                  # Unit test files
├── docs/                      # Internal documentation and architecture notes
├── docker/                    # Docker Compose configs and Nginx config
├── public/                    # Static assets (fonts, images, maps)
├── scripts/                   # Utility scripts
├── middleware.ts              # Next.js edge middleware (auth check)
├── next.config.ts             # Next.js config (standalone output, legacy redirects)
└── prisma/                    # (see above)
```

## Directory Purposes

**`src/app/(admin)/admin/`:**
- Purpose: All admin pages behind SUPER_ADMIN/PROGRAM_ADMIN role gate
- Contains: Competition management, round config, project management, jury groups, members, programs, reports, audit, awards, settings, messages, mentors, partners, learning
- Key files: `layout.tsx` (role guard + edition selector), `admin/page.tsx` (dashboard), `admin/rounds/[roundId]/page.tsx` (round detail — largest page)

**`src/app/(jury)/jury/`:**
- Purpose: Jury evaluation interface behind JURY_MEMBER role gate
- Contains: Competitions list, round overview, project list, evaluate page, deliberation, live voting, learning resources, awards
- Key files: `layout.tsx` (role guard + onboarding check), `competitions/[roundId]/projects/[projectId]/evaluate/page.tsx` (evaluation form)

**`src/app/(applicant)/applicant/`:**
- Purpose: Applicant dashboard behind APPLICANT role gate
- Contains: Competition progress, documents, evaluations received, mentor chat, resources, team
- Key files: `layout.tsx`, `applicant/page.tsx`

**`src/app/(mentor)/mentor/`:**
- Purpose: Mentor workspace behind MENTOR role gate
- Contains: Project list, workspace per project, resources
- Key files: `layout.tsx`, `mentor/workspace/[projectId]/page.tsx`

**`src/app/(observer)/observer/`:**
- Purpose: Read-only view behind OBSERVER role gate
- Contains: Projects, reports
- Key files: `layout.tsx`

**`src/app/(public)/`:**
- Purpose: No-auth-required pages
- Contains: Application form (`apply/[slug]`), edition application (`apply/edition/[programSlug]`), live scores display (`live-scores/[sessionId]`), audience vote (`vote/[sessionId]`), submission status (`my-submission/[id]`), email change password
- Key files: `apply/[slug]/page.tsx` (application wizard)

**`src/app/(auth)/`:**
- Purpose: Auth flow pages
- Contains: Login, verify (magic link), verify-email, accept-invite, onboarding, set-password, error
- Key files: `login/page.tsx`, `onboarding/page.tsx`, `accept-invite/page.tsx`

**`src/app/api/`:**
- Purpose: Next.js route handlers for non-tRPC API
- Contains:
  - `trpc/[trpc]/` — tRPC HTTP adapter (GET + POST)
  - `auth/[...nextauth]/` — NextAuth handler
  - `cron/` — Cron job endpoints (audit-cleanup, digest, draft-cleanup, reminders)
  - `live-voting/stream/` — SSE stream for live voting
  - `files/bulk-download/` — Bulk file download handler
  - `storage/local/` — Local dev storage handler
  - `health/` — DB health check endpoint

**`src/server/routers/`:**
- Purpose: tRPC domain routers, one file per domain
- Contains: 44+ router files assembled in `_app.ts`
- Key files: `competition.ts`, `round.ts`, `roundEngine.ts`, `evaluation.ts`, `filtering.ts`, `deliberation.ts`, `resultLock.ts`, `roundAssignment.ts`, `assignment.ts`, `project.ts`, `user.ts`, `program.ts`

**`src/server/services/`:**
- Purpose: All business logic — state machines, AI integrations, external service calls
- Contains:
  - `round-engine.ts` — Round and project state machine
  - `deliberation.ts` — Deliberation session lifecycle (DELIB_OPEN → VOTING → TALLYING → DELIB_LOCKED)
  - `round-assignment.ts` — Jury assignment generation with policy enforcement
  - `smart-assignment.ts` — Scoring algorithm (tag overlap, bio match, workload, geo-diversity, COI, availability)
  - `submission-manager.ts` — Submission window lifecycle and file requirement enforcement
  - `result-lock.ts` — Immutable result locking with snapshot
  - `live-control.ts` — Live ceremony cursor management
  - `competition-context.ts` — Cross-cutting context resolver
  - `ai-filtering.ts`, `ai-assignment.ts`, `ai-evaluation-summary.ts`, `ai-tagging.ts`, `ai-award-eligibility.ts`, `ai-shortlist.ts` — AI feature services
  - `anonymization.ts` — PII stripping before AI calls
  - `notification.ts`, `in-app-notification.ts`, `evaluation-reminders.ts`, `email-digest.ts` — Notification services
  - `assignment-policy.ts`, `assignment-intent.ts` — Policy governance for assignments
  - `mentor-matching.ts`, `mentor-workspace.ts` — Mentor domain services

**`src/components/admin/round/`:**
- Purpose: Components for the round detail page (the most complex admin page)
- Key files: `filtering-dashboard.tsx`, `project-states-table.tsx`

**`src/components/admin/rounds/config/`:**
- Purpose: Per-RoundType config form sections
- Contains: Config UI for each round type (`intake-config.tsx`, `evaluation-config.tsx`, etc.)

**`src/components/shared/`:**
- Purpose: Domain-agnostic reusable components
- Contains: `page-header.tsx`, `status-badge.tsx`, `file-upload.tsx`, `file-viewer.tsx`, `pagination.tsx`, `notification-bell.tsx`, `edition-selector.tsx`, `empty-state.tsx`, `loading-spinner.tsx`, and others

**`src/components/ui/`:**
- Purpose: shadcn/ui primitive components (never modified directly)
- Contains: `button.tsx`, `card.tsx`, `dialog.tsx`, `form.tsx`, `select.tsx`, `table.tsx`, etc.

**`src/components/layouts/`:**
- Purpose: Role-specific navigation shells
- Contains: `admin-sidebar.tsx`, `jury-nav.tsx`, `mentor-nav.tsx`, `observer-nav.tsx`, `applicant-nav.tsx`, `role-nav.tsx`, `admin-edition-wrapper.tsx`

**`src/lib/trpc/`:**
- Purpose: tRPC client configuration
- Contains:
  - `client.ts` — `createTRPCReact<AppRouter>()` export (client components use `import { trpc } from '@/lib/trpc/client'`)
  - `server.ts` — Server-side caller for Server Components
  - `index.ts` — Provider setup (TRPCProvider + QueryClientProvider)

**`src/types/`:**
- Purpose: Shared TypeScript types not generated by Prisma
- Contains:
  - `competition.ts` — Composite types with nested relations (e.g., `CompetitionWithRounds`, `RoundWithRelations`)
  - `competition-configs.ts` — Per-RoundType Zod config schemas and inferred TypeScript types
  - `wizard-config.ts` — Application wizard step configuration types

## Key File Locations

**Entry Points:**
- `middleware.ts` — Edge middleware (auth check before every request)
- `src/app/api/trpc/[trpc]/route.ts` — tRPC HTTP handler
- `src/app/api/auth/[...nextauth]/route.ts` — Auth handler
- `src/server/routers/_app.ts` — Root tRPC router

**Configuration:**
- `prisma/schema.prisma` — Database schema
- `next.config.ts` — Next.js configuration + legacy route redirects
- `src/lib/auth.config.ts` — Edge-compatible NextAuth config + Session type augmentations
- `src/lib/auth.ts` — Full NextAuth configuration with providers
- `src/server/trpc.ts` — tRPC initialization and all procedure type definitions
- `src/server/context.ts` — tRPC context (session, prisma, ip, userAgent)
- `tsconfig.json` — TypeScript strict mode config with `@/` path alias

**Core Logic:**
- `src/server/services/round-engine.ts` — Round state machine
- `src/server/services/deliberation.ts` — Deliberation state machine
- `src/server/services/round-assignment.ts` — Assignment generation
- `src/server/services/smart-assignment.ts` — Scoring algorithm
- `src/server/services/competition-context.ts` — Context resolver
- `src/types/competition-configs.ts` — Zod schemas for round configs
- `src/server/utils/audit.ts` — Audit logging utility

**Testing:**
- `tests/setup.ts` — Vitest setup with Prisma client
- `tests/helpers.ts` — Test data factories
- `tests/unit/` — Unit test files
- `vitest.config.ts` — Vitest configuration

## Naming Conventions

**Files:**
- kebab-case for all source files: `round-engine.ts`, `admin-sidebar.tsx`, `use-live-voting-sse.ts`
- Router files match domain name: `competition.ts`, `roundEngine.ts` (camelCase variants also seen for compound names)
- Service files use kebab-case: `round-assignment.ts`, `ai-filtering.ts`, `result-lock.ts`

**Directories:**
- kebab-case for all directories: `admin/`, `round-assignment/`, `apply-steps/`
- Route group segments use parentheses per Next.js convention: `(admin)`, `(jury)`, `(public)`
- Dynamic segments use square brackets: `[roundId]`, `[projectId]`, `[trpc]`

**Components:**
- PascalCase exports: `AdminSidebar`, `FilteringDashboard`, `JurorProgressDashboard`
- Component files kebab-case: `admin-sidebar.tsx`, `filtering-dashboard.tsx`

**Types:**
- `type` keyword preferred over `interface` (TypeScript strict mode project)
- Prisma-generated types used directly where possible; composite types in `src/types/`
- Zod schemas named `[Domain]ConfigSchema`; inferred types named `[Domain]Config`

## Where to Add New Code

**New tRPC Domain Router:**
- Router file: `src/server/routers/[domain].ts`
- Register in: `src/server/routers/_app.ts`
- Follow pattern: import from `../trpc`, use typed procedure (`adminProcedure`, `juryProcedure`, etc.), call `logAudit()` on mutations

**New Business Logic Service:**
- Implementation: `src/server/services/[domain].ts`
- Accept `prisma: PrismaClient | any` as parameter (for transaction compatibility)
- Return typed result objects `{ success: boolean, errors?: string[] }` for state machine functions
- Call `logAudit()` for all state changes
- Never import tRPC types — services are tRPC-agnostic

**New Admin Page:**
- Page file: `src/app/(admin)/admin/[section]/page.tsx`
- Layout guard is inherited from `src/app/(admin)/layout.tsx` — no additional role check needed
- Use `export const dynamic = 'force-dynamic'` for data-fetching pages
- Fetch data server-side in page component using `auth()` + `prisma` directly, or use client component with tRPC hooks

**New Jury Page:**
- Page file: `src/app/(jury)/jury/[section]/page.tsx`
- Layout guard in `src/app/(jury)/layout.tsx` checks `JURY_MEMBER` role and onboarding completion

**New Public Page:**
- Page file: `src/app/(public)/[section]/page.tsx`
- No auth guard — fully public

**New Component (domain-specific):**
- Admin component: `src/components/admin/[subdomain]/[component-name].tsx`
- Jury component: `src/components/jury/[component-name].tsx`
- Shared component: `src/components/shared/[component-name].tsx`

**New shadcn/ui Primitive:**
- Location: `src/components/ui/[component].tsx` (generated via `npx shadcn@latest add [component]`)

**New Round Config Schema:**
- Add Zod schema to `src/types/competition-configs.ts` following existing pattern
- Add to `RoundConfigMap` discriminated union
- Update `validateRoundConfig()` and `safeValidateRoundConfig()` switch statements
- Add config UI component to `src/components/admin/rounds/config/`

**Utilities:**
- Shared server+client helpers: `src/lib/utils.ts` or new `src/lib/[utility].ts`
- Server-only utilities: `src/server/utils/[utility].ts`
- Custom React hooks: `src/hooks/use-[name].ts`

## Special Directories

**`prisma/migrations/`:**
- Purpose: Auto-generated SQL migration files
- Generated: Yes (by `prisma migrate dev`)
- Committed: Yes

**`.next/`:**
- Purpose: Next.js build output cache
- Generated: Yes
- Committed: No

**`docs/`:**
- Purpose: Internal architecture notes, redesign plans, GDPR documentation, feature plans
- Generated: No
- Committed: Yes

**`prototypes/`:**
- Purpose: HTML/CSS prototype mockups for admin redesign
- Generated: No
- Committed: Yes

**`docker/`:**
- Purpose: Docker Compose files for production and dev stacks; Nginx reverse proxy config
- Generated: No
- Committed: Yes

**`.planning/`:**
- Purpose: GSD planning documents (codebase analysis, implementation plans)
- Generated: By GSD tooling
- Committed: No (gitignored)

**`.serena/`:**
- Purpose: Serena MCP project cache and memories
- Generated: Yes
- Committed: No

---

*Structure analysis: 2026-02-26*
