- Add mobile hamburger menu with full navigation - Fix touch support for Services dropdown - Add form validation and accessibility labels to contact form - Add carousel position indicators and swipe support - Add scroll-triggered animations with useInView hook - Add sticky mobile CTA bar - Improve Remote Support section mobile layout - Add animated background blobs - Add language selector (EN indicator) - Optimize hero image with priority flag Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.7 KiB
3.7 KiB
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
# 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 insrc/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)
// ✅ 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/<module>/schema.ts - Types are derived:
export type X = z.infer<typeof xSchema> - Query params use
z.coerce.*for URL strings
BFF Controllers
- Controllers are thin: no business logic, no Zod imports
- Use
createZodDto(schema)+ globalZodValidationPipe - 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/<feature>/own:hooks/(React Query)services/(API calls)components/andviews/(UI)
Code Standards
- No
anyin public APIs - No
console.login production (use logger) - TypeScript strict mode enabled
- Always read docs before guessing endpoint behavior:
docs/development/for BFF/Portal/Domain patternsdocs/architecture/for system boundariesdocs/integrations/for external API details