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