- Added detailed service highlights, how it works steps, and FAQs to the Public VPN Plans view. - Introduced new components: CtaButton, FeaturedServiceCard, ProcessStep, ServiceCard, ServiceShowcaseCard, TrustBadge, TrustIndicators, HowItWorks, ServiceCTA, and ServiceFAQ for improved layout and functionality. - Implemented a new design for the landing page with enhanced visuals and user engagement elements. - Updated the VPN plans section to include a more informative and visually appealing layout.
5.5 KiB
5.5 KiB
CLAUDE.md
Instructions for Claude Code working in this repository.
Agent Behavior
Do NOT run long-running processes without explicit permission:
pnpm dev,pnpm dev:start,npm start,npm run dev- Any command that starts servers, watchers, or blocking processes
Always ask first before:
- Starting development servers
- Running Docker containers
- Executing build watchers
- Any process that won't terminate on its own
Before coding: Read relevant docs. Never guess endpoint behavior or payload shapes.
Quick Reference
# Build domain (required after domain changes)
pnpm domain:build
# Type check & lint
pnpm type-check
pnpm lint
# Database
pnpm db:migrate
pnpm db:generate
# Tests
pnpm test
pnpm --filter @customer-portal/bff test
Ports: Frontend :3000 | Backend :4000/api | Prisma Studio :5555
Architecture
Monorepo
apps/
├── portal/ # Next.js 15 (React 19, Tailwind, shadcn/ui)
└── bff/ # NestJS 11 (Prisma, BullMQ, Zod)
packages/
└── domain/ # Shared contracts, schemas, provider mappers
Three-Layer Boundary
| Layer | Location | Purpose |
|---|---|---|
| Domain | packages/domain/ |
Contracts, Zod schemas, provider mappers |
| BFF | apps/bff/ |
HTTP boundary, orchestration, integrations |
| Portal | apps/portal/ |
UI layer, thin route wrappers over feature modules |
Systems of Record
- WHMCS: Billing, subscriptions, invoices, authoritative addresses
- Salesforce: CRM (Accounts, Contacts, Cases), order snapshots
- Portal: UI + BFF orchestration
Import Rules (ESLint Enforced)
// Allowed (Portal + BFF)
import type { Invoice } from "@customer-portal/domain/billing";
import { invoiceSchema } from "@customer-portal/domain/billing";
import { Formatting } from "@customer-portal/domain/toolkit";
// Allowed (BFF only)
import { Whmcs } from "@customer-portal/domain/billing/providers";
// Forbidden everywhere
import { Billing } from "@customer-portal/domain"; // root import
import { Invoice } from "@customer-portal/domain/billing/contract"; // deep import
// Forbidden in Portal
import { Whmcs } from "@customer-portal/domain/billing/providers"; // provider adapters
Domain Package
Each module follows:
packages/domain/<module>/
├── contract.ts # Normalized types (provider-agnostic)
├── schema.ts # Zod validation
├── index.ts # Public exports
└── providers/ # Provider-specific (BFF-only)
└── whmcs/
├── raw.types.ts # Raw API response types
└── mapper.ts # Transform raw → domain
Key principle: Map once in domain mappers, use domain types everywhere.
Portal Structure
apps/portal/src/
├── app/ # Next.js App Router (thin shells, NO API calls)
├── components/ # Atomic: atoms/ molecules/ organisms/ templates/
├── core/ # Infrastructure: api/, logger/, providers/
├── features/ # Feature modules (api/, stores/, hooks/, views/)
└── shared/ # Cross-feature: hooks/, utils/, constants/
Feature Module Pattern
features/<name>/
├── api/ # Data fetching (uses core/api/apiClient)
├── stores/ # Zustand state
├── hooks/ # React Query hooks
├── components/ # Feature UI
├── views/ # Page-level views
└── index.ts # Public exports (barrel)
Rules:
- Pages are thin wrappers importing views from features
- No API calls in
app/directory - No business logic in frontend; use services and APIs
BFF Patterns
Integration Layer
apps/bff/src/integrations/{provider}/
├── services/
│ ├── {provider}-connection.service.ts
│ └── {provider}-{entity}.service.ts
└── utils/
└── {entity}-query-builder.ts
Data Flow
External API → Integration Service → Domain Mapper → Domain Type → Use Directly
(fetch + query) (transform once) (return)
Integration services:
- Build queries (SOQL, API params)
- Execute API calls
- Use domain mappers to transform
- Return domain types
- NO additional mapping or business logic
Controllers
- Thin: no business logic, no Zod imports
- Use
createZodDto(schema)+ globalZodValidationPipe
Validation (Zod-First)
- Schemas in domain:
packages/domain/<module>/schema.ts - Derive types:
export type X = z.infer<typeof xSchema> - Query params: use
z.coerce.*for URL strings
Code Standards
- No
anyin public APIs - No
console.log(use logger:nestjs-pinofor BFF,@/core/loggerfor Portal) - Avoid
V2suffix in service names - No unsafe assertions
- Reuse existing types and functions; extend when needed
Documentation
Read before implementing:
| Topic | Location |
|---|---|
| Overview | docs/README.md |
| BFF patterns | docs/development/bff/integration-patterns.md |
| Portal architecture | docs/development/portal/architecture.md |
| Domain structure | docs/development/domain/structure.md |
| Salesforce | docs/integrations/salesforce/ |
| WHMCS | docs/integrations/whmcs/ |