# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Customer Portal with BFF (Backend for Frontend) architecture. A pnpm monorepo with a Next.js 15 frontend, NestJS 11 backend, and shared domain layer. ## Common Commands ```bash # Development pnpm dev:start # Start PostgreSQL + Redis services pnpm dev # Start both apps with hot reload pnpm dev:all # Build domain + start both apps # Building pnpm build # Build all (domain first, then apps) pnpm domain:build # Build domain layer only # Quality checks pnpm lint # Run ESLint across all packages pnpm type-check # TypeScript type checking pnpm format:check # Check Prettier formatting # Database (Prisma) pnpm db:migrate # Run migrations pnpm db:generate # Generate Prisma client pnpm db:studio # Open Prisma Studio pnpm db:reset # Reset database # Testing pnpm test # Run tests across packages pnpm --filter @customer-portal/bff test # BFF tests (node --test) # Single package commands pnpm --filter @customer-portal/portal dev # Portal only pnpm --filter @customer-portal/bff dev # BFF only ``` ## Architecture ### Monorepo Structure ``` apps/ portal/ # Next.js 15 frontend (React 19, Tailwind CSS 4, shadcn/ui) bff/ # NestJS 11 backend (Prisma, PostgreSQL, Redis) packages/ domain/ # Shared types, Zod schemas, mappers (framework-agnostic) ``` ### System Boundaries - **Domain (`packages/domain/`)**: Shared contracts, Zod validation, cross-app utilities. Must be framework-agnostic. - **BFF (`apps/bff/`)**: NestJS HTTP boundary, orchestration, integrations (Salesforce/WHMCS/Freebit). - **Portal (`apps/portal/`)**: Next.js UI. Pages are thin wrappers over feature modules in `src/features/`. ### External Systems - **WHMCS**: Billing, subscriptions, invoices, authoritative address storage - **Salesforce**: CRM (Accounts, Contacts, Cases), order management - **Freebit**: SIM management ### Data Flow Portal → BFF → External Systems (WHMCS/Salesforce/Freebit) User mapping: `user_id ↔ whmcs_client_id ↔ sf_contact_id/sf_account_id` ## Import Rules (ESLint Enforced) ```ts // ✅ Correct (Portal + BFF) import type { Invoice } from "@customer-portal/domain/billing"; import { invoiceSchema } from "@customer-portal/domain/billing"; // ✅ Correct (BFF only) import { Whmcs } from "@customer-portal/domain/billing/providers"; // ❌ Forbidden import { Billing } from "@customer-portal/domain"; // no root imports import { Invoice } from "@customer-portal/domain/billing/contract"; // no deep imports ``` Portal must never import `providers` from domain. ## Key Patterns ### Validation (Zod-first) - Schemas live in `packages/domain//schema.ts` - Types are derived: `export type X = z.infer` - Query params use `z.coerce.*` for URL strings ### BFF Controllers - Controllers are thin: no business logic, no Zod imports - Use `createZodDto(schema)` + global `ZodValidationPipe` - Integrations transform data via domain mappers and return domain types ### Portal Features - Pages under `apps/portal/src/app/**` are wrappers (no API calls) - Feature modules at `apps/portal/src/features//` own: - `hooks/` (React Query) - `services/` (API calls) - `components/` and `views/` (UI) ## Code Standards - No `any` in public APIs - No `console.log` in production (use logger) - TypeScript strict mode enabled - Always read docs before guessing endpoint behavior: - `docs/development/` for BFF/Portal/Domain patterns - `docs/architecture/` for system boundaries - `docs/integrations/` for external API details