Assist_Design/CLAUDE.md

218 lines
5.8 KiB
Markdown
Raw Normal View History

# CLAUDE.md
Instructions for Claude Code working in this repository.
---
## Agent Behavior
**Always use `pnpm`** — never use `npm`, `yarn`, or `npx`:
- Use `pnpm exec` to run local binaries (e.g., `pnpm exec prisma migrate status`)
- Use `pnpm dlx` for one-off package execution (e.g., `pnpm dlx ts-prune`)
**Do NOT** run long-running processes without explicit permission:
- `pnpm dev`, `pnpm dev:start`, or any dev server commands
- 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
```bash
# 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)
```typescript
// 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**:
1. Build queries (SOQL, API params)
2. Execute API calls
3. Use domain mappers to transform
4. Return domain types
5. NO additional mapping or business logic
### Controllers
- Thin: no business logic, no Zod imports
- Use `createZodDto(schema)` + global `ZodValidationPipe`
---
## 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 `any` in public APIs
- No `console.log` (use logger: `nestjs-pino` for BFF, `@/core/logger` for Portal)
- Avoid `V2` suffix 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/` |