142 lines
5.9 KiB
Markdown
142 lines
5.9 KiB
Markdown
|
|
# 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*
|