Tech Stack
Languages & Runtimes
| Technology | Version | Usage |
|---|---|---|
| TypeScript | 5.9.3 | Everything - frontend, backend, packages, jobs, CLI |
| Node.js | 22 | Production runtime (Docker images) |
| Bun | 1.3.4 | Package manager, local dev runtime, script execution |
Why TypeScript everywhere? Full-stack type safety from database schema (Prisma) through API contracts to React components. Zod schemas bridge runtime validation with compile-time types.
Frontend
| Technology | Version | Purpose | Key File |
|---|---|---|---|
| Next.js | 16.2.0 | React framework, SSR, routing | apps/app/package.json |
| React | 19.2.3 | UI library | |
| TailwindCSS | 4.1.8 | Utility-first CSS | |
| Radix UI | Various | Accessible primitives | |
| @trycompai/design-system | 1.0.45 | Primary component library | Carbon icons |
| @trycompai/ui | 1.3.2 | Legacy components (being phased out) | |
| SWR | 2.3.4 | Client-side data fetching + caching | apps/app/src/lib/api-client.ts |
| TanStack React Query | 5.90.7 | Server state (used alongside SWR) | apps/app/src/app/providers.tsx |
| React Hook Form | 7.61.1 | Form state management | |
| Zod | 4.3.6 | Schema validation (forms + API) | |
| nuqs | 2.4.3 | URL query state management | |
| Zustand | 5.0.3 | Client-side state stores | |
| TipTap | 3.22.1 | Rich text editor (policies) | |
| Monaco Editor | — | Code editor | |
| XYFlow | 12.10.0 | Node/edge flow diagrams | |
| Three.js/R3F | — | 3D visualizations | |
| Framer Motion | 12.18.1 | Animations | |
| next-themes | — | Dark/light mode | |
| Sonner | 2.0.5 | Toast notifications |
Why Next.js 16? App Router for server components, streaming, and parallel data fetching. force-dynamic with revalidate: 0 for always-fresh compliance data.
Why SWR + React Query? SWR handles most data fetching with its simpler API. React Query provides dehydrate/hydrate for SSR state transfer with SuperJSON serialization.
Backend API
| Technology | Version | Purpose | Key File |
|---|---|---|---|
| NestJS | 11.0.1 | API framework | apps/api/src/main.ts |
| Better Auth | 1.4.22 | Session-based auth | apps/api/src/auth/auth.server.ts |
| Prisma | 7.6.0 | ORM + migrations | packages/db/prisma/schema/ |
| Swagger | 11.2.0 | API documentation | /api/docs endpoint |
| Helmet | — | Security headers | apps/api/src/main.ts:56 |
| class-validator | — | DTO validation | Global ValidationPipe |
| express | — | HTTP server (under NestJS) |
Why NestJS? Module system maps cleanly to domain boundaries (controls, policies, risks). Decorators (@UseGuards, @RequirePermission) enforce auth/RBAC declaratively. Built-in DI for testability.
Why Better Auth? Open-source, session-based (no JWT complexity), built-in organization/RBAC plugin, social OAuth, magic links, OTP - all needed features in one library.
Database
| Technology | Version | Purpose |
|---|---|---|
| PostgreSQL | 15+ | Primary database |
| pgvector | — | Vector similarity search (RAG) |
| pgcrypto | — | UUID generation, encryption |
| Prisma | 7.6.0 | ORM, migrations, type-safe queries |
| Upstash Redis | — | Caching (CORS origins, chat history) |
Schema stats: 45 .prisma files, 196 migrations, split by domain model.
ID strategy: Prefixed CUIDs generated at database level:
generate_prefixed_cuid('ctl'::text) -- → ctl_clx7abc123...
generate_prefixed_cuid('pol'::text) -- → pol_clx8def456...AI & LLM
| Technology | Purpose | Models Used |
|---|---|---|
Vercel AI SDK (ai) |
Unified LLM interface | All providers |
| @ai-sdk/openai | OpenAI provider | GPT-5, GPT-5-mini, GPT-4o, GPT-4o-mini |
| @ai-sdk/anthropic | Anthropic provider | Claude Opus 4.6, Claude Sonnet 4.6 |
| @ai-sdk/groq | Groq provider | Llama 4 Scout 17B |
| @ai-sdk/gateway | Dynamic model routing | Runtime model selection |
| pgvector | Vector embeddings | text-embedding-3-small |
Why multi-model? Cost and capability optimization. See 05-ai-and-llm.md for the full model selection matrix.
Background Jobs
| Technology | Version | Purpose |
|---|---|---|
| Trigger.dev | 4.4.3 | Job scheduling, retries, orchestration |
Two separate projects:
- API project: Cloud scans, integration checks, email, vendor assessment
- App project: Remediation, auditor content, onboarding, browser automation
Why Trigger.dev? TypeScript-native, built-in retry/backoff, batch operations, concurrency control, and metadata tracking. Replaces cron + queue systems.
Browser Automation
| Technology | Purpose |
|---|---|
| Browserbase | Cloud browser infrastructure |
| Stagehand v3 | AI-powered browser agent (Claude Sonnet) |
| Playwright | Browser automation protocol |
| Puppeteer | Alternative browser control |
Why Browserbase + Stagehand? Cloud-hosted persistent browser contexts per organization. Stagehand uses Claude to interpret natural-language task instructions and navigate web UIs for evidence collection.
Infrastructure & DevOps
| Technology | Purpose |
|---|---|
| Turbo | Monorepo build orchestration (15 concurrent tasks) |
| Docker | Multi-stage production builds |
| AWS ECS | Container orchestration |
| AWS S3 | File storage (attachments, questionnaires, knowledge base) |
| AWS CodeBuild | CI/CD pipeline |
| Resend | Transactional email |
| Stripe | Billing/subscriptions |
| PostHog | Product analytics + feature flags |
| Firecrawl | Web scraping for vendor research |
| Novu | Notification infrastructure |
| Husky | Git hooks (commit linting) |
| Semantic Release | Automated versioning/changelog |
| Syncpack | Dependency version consistency |
Testing
| Technology | Purpose | Location |
|---|---|---|
| Vitest | Frontend unit/integration tests | apps/app/ |
| Jest | Backend unit/integration tests | apps/api/ |
| @testing-library/react | React component testing | apps/app/ |
| Playwright | E2E tests | apps/app/ |
Notable Dependency Choices
What's NOT Used (and Why)
| Avoided | Why |
|---|---|
| JWT tokens | Session cookies are simpler, more secure for this multi-subdomain setup |
| GraphQL | REST with flat response format is sufficient; Swagger provides docs |
| Redux/MobX | Zustand for rare client state; SWR/React Query for server state |
| Prisma Accelerate | Direct Postgres connection; Redis for caching layer |
| tRPC | NestJS controllers with Swagger provide the typed API contract |
| Drizzle | Prisma chosen for migration tooling and schema splitting |
Package Manager: Bun
The project uses Bun exclusively (enforced in package.json). Key reasons:
- ~10x faster
installthan npm - Compatible with Node.js ecosystem
bunfig.tomluseslinker = "hoisted"for monorepo compatibility- Production still runs on Node.js 22 (Docker images)
Design System Migration
The codebase is actively migrating from @trycompai/ui (437 import sites) to @trycompai/design-system. The DS enforces:
- Carbon icons (not Lucide)
- No
classNameon core components (enforces design consistency) - Standard layout primitives:
PageLayout,PageHeader,Stack,HStack