# 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()` 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*