2025-09-29 13:36:40 +09:00
# Customer Portal Architecture
## 🏗️ **System Overview**
The Customer Portal is a modern monorepo with clean separation between frontend (Next.js) and backend (NestJS), designed for maintainability and scalability.
### **High-Level Structure**
```
apps/
portal/ # Next.js frontend
bff/ # NestJS Backend-for-Frontend
packages/
2025-12-23 15:55:58 +09:00
domain/ # Pure domain types, validation schemas, and utilities (isomorphic)
2025-09-29 13:36:40 +09:00
```
## 🎯 **Architecture Principles**
### **1. Separation of Concerns**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- **Dev vs Prod**: Clear separation with appropriate tooling
- **Services vs Apps**: Development runs apps locally, production containerizes everything
- **Configuration vs Code**: Environment variables for configuration, code for logic
### **2. Single Source of Truth**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- **One environment template**: `.env.example`
- **One Docker Compose** per environment
- **One script** per operation type
### **3. Clean Dependencies**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- **Portal**: Uses `@/lib/*` for shared utilities and services
- **BFF**: Feature-aligned modules with shared concerns in `src/common/`
- **Domain**: Framework-agnostic types and utilities
## 🚀 **Portal (Next.js) Architecture**
```
src/
app/ # App Router routes
components/ # Design system (atomic design)
atoms/ # Basic UI elements
molecules/ # Component combinations
organisms/ # Complex UI sections
templates/ # Page layouts
features/ # Feature modules (auth, billing, etc.)
lib/ # Core utilities and services
2025-10-02 17:19:39 +09:00
api/ # Zod-aware fetch client + helpers
2025-09-29 13:36:40 +09:00
hooks/ # Shared React hooks
utils/ # Utility functions
providers/ # Context providers
styles/ # Global styles
```
### **Conventions**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- Use `@/lib/*` for shared frontend utilities and services
- Feature modules own their `components/` , `hooks/` , `services/` , and `types/`
- Cross-feature UI belongs in `components/` (atomic design)
- Avoid duplicate layers - no `core/` or `shared/` inside apps
## 🔧 **BFF (NestJS) Architecture**
```
src/
modules/ # Feature-aligned modules
2025-12-23 15:55:58 +09:00
auth/ # Authentication and authorization
users/ # User management
2025-12-23 17:53:08 +09:00
me-status/ # Aggregated customer status (dashboard + gating signals)
2025-12-23 15:55:58 +09:00
id-mappings/ # Portal-WHMCS-Salesforce ID mappings
2025-12-25 15:48:57 +09:00
services/ # Services catalog (browsing/purchasing)
2025-12-23 15:55:58 +09:00
orders/ # Order creation and fulfillment
invoices/ # Invoice management
subscriptions/ # Service and subscription management
currency/ # Currency handling
support/ # Support case management
realtime/ # Server-Sent Events API
verification/ # ID verification
notifications/ # User notifications
health/ # Health check endpoints
2025-09-29 13:36:40 +09:00
core/ # Core services and utilities
2025-12-23 15:55:58 +09:00
infra/ # Infrastructure (database, cache, queue, email)
2025-09-29 13:36:40 +09:00
integrations/ # External service integrations
salesforce/ # Salesforce CRM integration
whmcs/ # WHMCS billing integration
2025-12-23 15:55:58 +09:00
freebit/ # Freebit SIM provider integration
sftp/ # SFTP file transfer
2025-09-29 13:36:40 +09:00
main.ts # Application entry point
```
### **Conventions**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- Prefer `modules/*` over flat directories per domain
- Keep DTOs and validators in-module
- Reuse `packages/domain` for domain types
- External integrations in dedicated modules
2025-12-25 15:48:57 +09:00
### **API Boundary: Public vs Account**
- **Public APIs** (`/api/public/*` ): strictly non-personalized endpoints intended for marketing pages and unauthenticated browsing.
- **Account APIs** (`/api/account/*` ): authenticated endpoints that may return personalized responses (e.g. eligibility-gated catalogs, SIM family discount availability).
2025-09-29 13:36:40 +09:00
## 📦 **Shared Packages**
2025-12-23 15:55:58 +09:00
### **Domain Package (`packages/domain/`)**
2025-10-03 14:26:55 +09:00
2025-12-23 15:55:58 +09:00
The domain package is the single source of truth for shared types, validation schemas, and utilities across both the BFF and Portal applications.
2025-10-03 14:26:55 +09:00
```
2025-12-23 15:55:58 +09:00
packages/domain/
├── auth/ # Authentication types and validation
├── billing/ # Invoice and payment types
2025-12-25 15:48:57 +09:00
├── services/ # Services catalog types
2025-12-23 15:55:58 +09:00
├── checkout/ # Checkout flow types
├── common/ # Shared utilities and base types
├── customer/ # Customer profile types
├── dashboard/ # Dashboard data types
├── mappings/ # ID mapping types (Portal-WHMCS-SF)
├── notifications/ # Notification types
├── opportunity/ # Salesforce opportunity types
├── orders/ # Order types and Salesforce mappings
├── payments/ # Payment method types
├── providers/ # Provider-specific type definitions
├── realtime/ # SSE event types
├── salesforce/ # Salesforce API types
├── sim/ # SIM lifecycle and Freebit types
├── subscriptions/ # Subscription types
├── support/ # Support case types
├── toolkit/ # Utility functions
└── index.ts # Public exports
2025-10-03 14:26:55 +09:00
```
2025-12-23 15:55:58 +09:00
#### **Key Principles**
2025-12-23 15:43:36 +09:00
2025-12-23 15:55:58 +09:00
- **Framework-agnostic**: No NestJS or React dependencies
- **Isomorphic**: Works in both Node.js and browser environments
- **Zod-first validation**: Schemas defined with Zod for runtime validation
- **Provider mappers**: Transform external API responses to domain types
2025-10-03 14:26:55 +09:00
2025-12-23 15:55:58 +09:00
#### **Usage**
2025-12-23 15:43:36 +09:00
2025-12-23 15:55:58 +09:00
Import via `@customer-portal/domain` :
2025-10-03 14:26:55 +09:00
2025-12-23 15:55:58 +09:00
```typescript
import { Invoice, SIM_LIFECYCLE_STAGE, OrderStatus } from "@customer -portal/domain";
import { invoiceSchema, orderSchema } from "@customer -portal/domain/validation";
```
2025-12-23 15:43:36 +09:00
2025-12-23 15:55:58 +09:00
#### **Integration with BFF**
2025-10-03 14:26:55 +09:00
2025-12-23 15:55:58 +09:00
The BFF integration layer (`apps/bff/src/integrations/` ) uses domain mappers to transform raw provider data:
2025-12-23 15:43:36 +09:00
2025-12-23 15:55:58 +09:00
```
External API → Raw Response → Domain Mapper → Domain Type → Use Everywhere
```
2025-10-03 14:26:55 +09:00
2025-12-23 15:55:58 +09:00
This ensures a single transformation point and consistent types across the application.
2025-12-23 15:43:36 +09:00
2025-12-23 15:55:58 +09:00
### **Logging**
2025-09-29 13:36:40 +09:00
2025-12-23 15:55:58 +09:00
Centralized logging is implemented in the BFF using `nestjs-pino` :
2025-12-23 15:43:36 +09:00
2025-12-23 15:55:58 +09:00
- **Structured JSON logging** for production
- **Correlation IDs** for request tracing
- **Automatic PII redaction** for security
2025-09-29 13:36:40 +09:00
## 🔗 **Integration Architecture**
### **API Client**
2025-12-23 15:43:36 +09:00
2025-10-02 17:19:39 +09:00
- **Implementation**: Fetch wrapper using shared Zod schemas from `@customer-portal/domain`
- **Features**: CSRF protection, auth handling, consistent `ApiResponse` helpers
2025-09-29 13:36:40 +09:00
- **Location**: `apps/portal/src/lib/api/`
### **External Services**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- **WHMCS**: Billing system integration
- **Salesforce**: CRM and order management
- **Redis**: Caching and session storage
- **PostgreSQL**: Primary data store
## 🔒 **Security Architecture**
### **Authentication Flow**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- Portal-native authentication with JWT tokens
- Optional MFA support
- Secure token rotation with Redis backing
### **Error Handling**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- Never leak sensitive details to end users [[memory:6689308]]
- Centralized error mapping to user-friendly messages
- Comprehensive audit trails
### **Data Protection**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- PII minimization with encryption at rest/in transit
- Row-level security (users can only access their data)
- Idempotency keys on all mutating operations
## 🚀 **Development Workflow**
### **Path Aliases**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- **Portal**: `@/*` , `@/lib/*` , `@/features/*` , `@/components/*`
- **BFF**: `@/*` mapped to `apps/bff/src`
- **Domain**: Import via `@customer-portal/domain`
### **Code Quality**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- Strict TypeScript rules enforced repository-wide
- ESLint and Prettier for consistent formatting
- Pre-commit hooks for quality gates
2025-12-23 17:53:08 +09:00
### **Domain Build Hygiene**
The domain package (`packages/domain` ) is consumed via committed `dist/` outputs.
- **Build**: `pnpm domain:build`
- **Verify dist drift** (CI-friendly): `pnpm domain:check-dist`
2025-09-29 13:36:40 +09:00
## 📈 **Performance & Scalability**
### **Caching Strategy**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- **Invoices**: 60-120s per page; bust on WHMCS webhook
2025-12-23 15:43:36 +09:00
- **Cases**: 30-60s; bust after create/update
2025-09-29 13:36:40 +09:00
- **Catalog**: 5-15m; manual bust on changes
- **Keys include user_id** to prevent cross-user leakage
### **Database Optimization**
2025-12-23 15:43:36 +09:00
2025-09-29 13:36:40 +09:00
- Connection pooling with Prisma
- Proper indexing on frequently queried fields
- Optional mirrors for external system data
---
2025-12-23 15:43:36 +09:00
_This architecture supports clean, maintainable code with clear separation of concerns and production-ready security._