# Technology Stack

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

## Languages

**Primary:**
- TypeScript 5.7 - All application code (strict mode, `noEmit`, `ES2022` target)

**Secondary:**
- CSS (Tailwind utility classes only, no custom CSS files)

## Runtime

**Environment:**
- Node.js >=20.0.0 (engines field in `package.json`)

**Package Manager:**
- npm (standard)
- Lockfile: `package-lock.json` present

## Frameworks

**Core:**
- Next.js 15.1 - App Router, standalone output, Turbopack dev mode
- React 19.0 - Server Components by default; `'use client'` only where needed

**API Layer:**
- tRPC 11 (RC build `11.0.0-rc.678`) - End-to-end typed RPC, superjson transformer
- `@trpc/server`, `@trpc/client`, `@trpc/react-query` - All at same version

**Data:**
- Prisma 6.19 - ORM and schema-first migrations; binary targets: `native`, `windows`, `linux-musl-openssl-3.0.x`
- `@prisma/client` 6.19 - Generated client with connection pool (limit=20, timeout=10)

**Auth:**
- NextAuth v5 (Beta 25) - JWT strategy, 24-hour sessions; Prisma adapter via `@auth/prisma-adapter`

**Forms & Validation:**
- Zod 3.24 - Input validation for all tRPC procedures
- React Hook Form 7.54 - Client-side form state; `@hookform/resolvers` for Zod integration

**UI Components:**
- shadcn/ui (configured via `components.json`) - Radix UI primitives styled with Tailwind
- Radix UI primitives: alert-dialog, avatar, checkbox, collapsible, dialog, dropdown-menu, label, popover, progress, radio-group, scroll-area, select, separator, slider, slot, switch, tabs, toggle, tooltip (all `^1.x` or `^2.x`)
- Tailwind CSS 4.1 - Utility-first, `@tailwindcss/postcss` plugin
- Lucide React 0.563 - Icon library (import-optimized via `next.config.ts`)
- Framer Motion 11 (`motion` package) - Animation
- Tremor 3.18 - Data visualization / chart components
- `@blocknote/react`, `@blocknote/core`, `@blocknote/shadcn` 0.46 - Rich text block editor
- next-themes 0.4 - Dark/light mode switching
- Sonner 2.0 - Toast notifications

**Testing:**
- Vitest 4.0 - Test runner, `fileParallelism: false`, `pool: 'forks'`
- `@playwright/test` 1.49 - E2E test runner

**Build/Dev:**
- Turbopack (built into Next.js 15) - Dev server via `next dev --turbopack`
- tsx 4.19 - Direct TypeScript execution for scripts and seeds
- ESLint 9.17 + `eslint-config-next` 15.1 - Linting
- Prettier 3.4 + `prettier-plugin-tailwindcss` 0.7 - Formatting

## Key Dependencies

**Critical:**
- `superjson` 2.2 - tRPC transformer; enables Date, Map, Set serialization over the wire
- `bcryptjs` 3.0 - Password hashing (no native bcrypt — pure JS for portability)
- `minio` 8.0 - S3-compatible object storage client
- `nodemailer` 7.0 - SMTP email delivery
- `openai` 6.16 - OpenAI SDK for AI features
- `@anthropic-ai/sdk` 0.78 - Anthropic Claude SDK; wrapped in adapter matching OpenAI interface
- `@notionhq/client` 2.3 - Notion API for project import
- `csv-parse` 6.1 - CSV import for candidatures seed

**Infrastructure:**
- `date-fns` 4.1 - Date manipulation
- `use-debounce` 10.0 - Input debouncing
- `@tanstack/react-query` 5.62 - Server state caching (used via tRPC)
- `@dnd-kit/core`, `@dnd-kit/sortable` - Drag-and-drop ordering UI
- `leaflet` 1.9 + `react-leaflet` 5.0 - Map rendering
- `mammoth` 1.11 - DOCX to HTML conversion for file content extraction
- `pdf-parse` 2.4, `unpdf` 1.4 - PDF text extraction
- `html2canvas` 1.4, `jspdf` 4.1, `jspdf-autotable` 5.0 - PDF export for reports
- `franc` 6.2 - Language detection for multilingual project content
- `papaparse` 5.4 - CSV parsing in browser
- `cmdk` 1.0 - Command palette component
- `react-easy-crop` 5.5 - Avatar image cropping
- `react-phone-number-input` 3.4 - International phone number input
- `react-day-picker` 9.13 - Date picker calendar

## Configuration

**TypeScript:**
- `src/tsconfig.json`: strict mode, `ES2022` target, path alias `@/*` → `./src/*`, bundler module resolution
- Config file: `tsconfig.json`

**Next.js:**
- Config file: `next.config.ts`
- `output: 'standalone'` for Docker deployment
- `typedRoutes: true` for compile-time route safety
- `serverExternalPackages: ['@prisma/client', 'minio']` — not bundled

**Tailwind:**
- Config file: `tailwind.config.ts`
- PostCSS via `postcss.config.mjs` + `@tailwindcss/postcss`
- Brand palette: Primary Red `#de0f1e`, Dark Blue `#053d57`, White `#fefefe`, Teal `#557f8c`

**Vitest:**
- Config file: `vitest.config.ts`
- `environment: 'node'`, `testTimeout: 30000`, sequential execution
- Path alias mirrors tsconfig

**Environment:**
- Required vars: `DATABASE_URL`, `NEXTAUTH_URL`, `NEXTAUTH_SECRET`, `MINIO_ENDPOINT`, `MINIO_ACCESS_KEY`, `MINIO_SECRET_KEY`, `MINIO_BUCKET`, `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `EMAIL_FROM`, `OPENAI_API_KEY`, `CRON_SECRET`
- Optional vars: `MINIO_PUBLIC_ENDPOINT`, `OPENAI_MODEL` (default: `gpt-4o`), `OPENAI_BASE_URL`, `ANTHROPIC_API_KEY`, `SESSION_MAX_AGE` (default: 86400), `MAX_FILE_SIZE` (default: 524288000), `LOG_LEVEL`, `MAGIC_LINK_EXPIRY` (default: 900)
- All settings also configurable via `SystemSettings` DB table (DB takes priority over env vars)

**Build:**
- `npm run build` → `next build` → produces `.next/standalone/` output
- `npm run typecheck` → `tsc --noEmit` (no emit, type checking only)

## Platform Requirements

**Development:**
- Node.js >=20.0.0
- PostgreSQL 16 (via Docker or local)
- MinIO instance (optional in dev, defaults to `localhost:9000`)

**Production:**
- Docker (compose file: `docker/docker-compose.yml`)
- PostgreSQL 16 (`postgres:16-alpine` image) in Docker network
- Next.js app runs as standalone Node.js server on port 7600
- MinIO and Poste.io are external pre-existing services on VPS
- Nginx reverse proxy with SSL (external, not in compose)
- CI/CD: Gitea Actions (image pushed to container registry, `pull_policy: always`)
- App entrypoint (`docker/docker-entrypoint.sh`): runs `prisma migrate deploy` → `prisma generate` → auto-seeds if DB empty → `node server.js`

---

*Stack analysis: 2026-02-26*
