# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview **Xpeditis** is a B2B SaaS maritime freight booking platform. Freight forwarders search and compare real-time shipping rates, book containers, and manage shipments. Built as a monorepo with NestJS backend (Hexagonal Architecture) and Next.js 14 frontend. ## Development Commands ```bash # Start infrastructure (PostgreSQL + Redis + MinIO) docker-compose up -d # Install dependencies npm install && cd apps/backend && npm install && cd ../frontend && npm install # Run database migrations cd apps/backend && npm run migration:run # Start development servers npm run backend:dev # http://localhost:4000, Swagger: /api/docs npm run frontend:dev # http://localhost:3000 ``` ### Testing ```bash # Backend (from apps/backend/) npm test # Unit tests npm test -- booking.entity.spec.ts # Single file npm run test:cov # With coverage npm run test:integration # Integration tests (needs DB/Redis) npm run test:e2e # E2E tests # Frontend (from apps/frontend/) npm test npx playwright test # E2E tests ``` ### Database Migrations ```bash cd apps/backend npm run migration:generate -- src/infrastructure/persistence/typeorm/migrations/MigrationName npm run migration:run npm run migration:revert ``` ### Build ```bash npm run backend:build # Compiles TS with path alias resolution (tsc-alias) npm run frontend:build # Next.js production build ``` ## Architecture ### Hexagonal Architecture (Backend) ``` apps/backend/src/ ├── domain/ # CORE - Pure TypeScript, NO framework imports │ ├── entities/ # Booking, RateQuote, User (with private props, static create()) │ ├── value-objects/# Money, Email, BookingNumber (immutable, validated) │ ├── services/ # Domain services │ ├── ports/ │ │ ├── in/ # Use case interfaces │ │ └── out/ # Repository interfaces (SPIs) │ └── exceptions/ # Domain exceptions ├── application/ # Controllers, DTOs, Guards (depends ONLY on domain) └── infrastructure/ # TypeORM, Redis, Carrier APIs (depends ONLY on domain) ``` **Critical Rules**: - Domain layer: Zero imports from NestJS, TypeORM, Redis - Dependencies flow inward: Infrastructure → Application → Domain - Use path aliases: `@domain/*`, `@application/*`, `@infrastructure/*` - Domain tests run without NestJS TestingModule ### Frontend (Next.js 14 App Router) ``` apps/frontend/ ├── app/ # App Router pages │ ├── dashboard/ # Protected routes │ │ ├── bookings/ # Booking management │ │ ├── admin/ # Admin features (ADMIN role) │ │ └── settings/ # User/org settings │ └── carrier/ # Carrier portal (magic link auth) └── src/ ├── components/ # React components (shadcn/ui in ui/) ├── hooks/ # useBookings, useNotifications ├── lib/api/ # API client modules └── types/ # TypeScript definitions ``` Path aliases: `@/*` → `./src/*`, `@/components/*`, `@/lib/*`, `@/hooks/*` ## Key Patterns ### Entity Pattern (Domain) ```typescript export class Booking { private readonly props: BookingProps; static create(props: Omit): Booking { ... } updateStatus(newStatus: BookingStatus): Booking { // Returns new instance return new Booking({ ...this.props, status: newStatus }); } } ``` ### Repository Pattern - Interface in `domain/ports/out/booking.repository.ts` - Implementation in `infrastructure/persistence/typeorm/repositories/typeorm-booking.repository.ts` - Separate mappers for Domain ↔ ORM entity conversions ### Circuit Breaker (External APIs) - Library: `opossum`, Timeout: 5s - Used for carrier API calls (Maersk, MSC, CMA CGM) ### Caching - Redis with 15-min TTL for rate quotes - Cache key format: `rate:{origin}:{destination}:{containerType}` ## Business Rules - Booking number format: `WCM-YYYY-XXXXXX` - Rate quotes expire after 15 minutes - Multi-currency: USD, EUR - RBAC Roles: ADMIN, MANAGER, USER, VIEWER, CARRIER ### Carrier Portal Workflow 1. Admin creates CSV booking → assigns carrier 2. Email with magic link sent (1-hour expiry) 3. Carrier auto-login → accept/reject booking 4. Activity logged in `carrier_activities` table ## Tech Stack **Backend**: NestJS 10, TypeORM 0.3, PostgreSQL 15, Redis 7, Argon2, Pino, Sentry **Frontend**: Next.js 14, React 18, TanStack Query/Table, React Hook Form + Zod, Tailwind + shadcn/ui, Socket.IO ## Common Pitfalls - Never import NestJS/TypeORM in domain layer - Never use `any` type (strict mode enabled) - Never use `DATABASE_SYNC=true` in production - Never modify applied migrations - create new ones - Always validate DTOs with `class-validator` - Always create mappers for Domain ↔ ORM conversions ## Adding a New Feature 1. **Domain Entity** → `domain/entities/*.entity.ts` (pure TS, unit tests) 2. **Value Objects** → `domain/value-objects/*.vo.ts` (immutable) 3. **Port Interface** → `domain/ports/out/*.repository.ts` 4. **ORM Entity** → `infrastructure/persistence/typeorm/entities/*.orm-entity.ts` 5. **Generate Migration** → `npm run migration:generate -- ...` 6. **Repository Impl** → `infrastructure/persistence/typeorm/repositories/` 7. **DTOs** → `application/dto/` (with class-validator decorators) 8. **Controller** → `application/controllers/` (with Swagger decorators) 9. **Module** → Register and import in `app.module.ts` ## Documentation - API Docs: http://localhost:4000/api/docs (Swagger) - Architecture: `docs/architecture.md` - Carrier Portal API: `apps/backend/docs/CARRIER_PORTAL_API.md` - Full docs index: `docs/README.md`