- Streamlined the README.md for clarity and conciseness. - Deleted outdated documentation files related to Freebit SIM management, SIM management API data flow, and various architectural guides to reduce clutter and improve maintainability. - Updated the last modified date in the README to reflect the latest changes.
7.1 KiB
7.1 KiB
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/
domain/ # Pure domain/types/utils (isomorphic)
logging/ # Centralized logging utilities
validation/ # Shared validation schemas
🎯 Architecture Principles
1. Separation of Concerns
- 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
- One environment template:
.env.example - One Docker Compose per environment
- One script per operation type
3. Clean Dependencies
- 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
api/ # Zod-aware fetch client + helpers
hooks/ # Shared React hooks
utils/ # Utility functions
providers/ # Context providers
styles/ # Global styles
Conventions
- Use
@/lib/*for shared frontend utilities and services - Feature modules own their
components/,hooks/,services/, andtypes/ - Cross-feature UI belongs in
components/(atomic design) - Avoid duplicate layers - no
core/orshared/inside apps
🔧 BFF (NestJS) Architecture
src/
modules/ # Feature-aligned modules
auth/ # Authentication
billing/ # Invoice and payment management
catalog/ # Product catalog
orders/ # Order processing
subscriptions/ # Service management
core/ # Core services and utilities
integrations/ # External service integrations
salesforce/ # Salesforce CRM integration
whmcs/ # WHMCS billing integration
common/ # Nest providers/interceptors/guards
main.ts # Application entry point
Conventions
- Prefer
modules/*over flat directories per domain - Keep DTOs and validators in-module
- Reuse
packages/domainfor domain types - External integrations in dedicated modules
📦 Shared Packages
Layered Type System Architecture
The codebase follows a strict layering pattern to ensure single source of truth for all types and prevent drift:
@customer-portal/contracts (Pure TypeScript types)
↓
@customer-portal/schemas (Runtime validation with Zod)
↓
@customer-portal/integrations (Mappers for external APIs)
↓
Applications (BFF, Portal)
1. Contracts Package (packages/contracts/)
- Purpose: Pure TypeScript interface definitions - single source of truth
- Contents: Cross-layer contracts for billing, subscriptions, payments, SIM, orders
- Exports: Organized by domain (e.g.,
@customer-portal/contracts/billing) - Rule: ZERO runtime dependencies, only pure types
2. Schemas Package (packages/schemas/)
- Purpose: Runtime validation schemas using Zod
- Contents: Matching Zod validators for each contract + integration-specific payload schemas
- Exports: Organized by domain and integration provider
- Usage: Validate external API responses, request payloads, and user input
3. Integration Packages (packages/integrations/)
- Purpose: Transform raw provider data into shared contracts
- Structure:
packages/integrations/whmcs/- WHMCS billing integrationpackages/integrations/freebit/- Freebit SIM provider integration
- Contents: Mappers, utilities, and helper functions
- Rule: Must use
@customer-portal/schemasfor validation at boundaries
4. Application Layers
- BFF (
apps/bff/): Import from contracts/schemas, never define duplicate interfaces - Portal (
apps/portal/): Import from contracts/schemas, use shared types everywhere - Rule: Applications only consume, never define domain types
Legacy: Domain Package (Deprecated)
- Status: Being phased out in favor of contracts + schemas
- Migration: Re-exports now point to contracts package for backward compatibility
- Rule: New code should import from
@customer-portal/contractsor@customer-portal/schemas
Logging Package
- Purpose: Centralized structured logging
- Features: Pino-based logging with correlation IDs
- Security: Automatic PII redaction memory:6689308
🔗 Integration Architecture
API Client
- Implementation: Fetch wrapper using shared Zod schemas from
@customer-portal/domain - Features: CSRF protection, auth handling, consistent
ApiResponsehelpers - Location:
apps/portal/src/lib/api/
External Services
- WHMCS: Billing system integration
- Salesforce: CRM and order management
- Redis: Caching and session storage
- PostgreSQL: Primary data store
🔒 Security Architecture
Authentication Flow
- Portal-native authentication with JWT tokens
- Optional MFA support
- Secure token rotation with Redis backing
Error Handling
- Never leak sensitive details to end users memory:6689308
- Centralized error mapping to user-friendly messages
- Comprehensive audit trails
Data Protection
- 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
- Portal:
@/*,@/lib/*,@/features/*,@/components/* - BFF:
@/*mapped toapps/bff/src - Domain: Import via
@customer-portal/domain
Code Quality
- Strict TypeScript rules enforced repository-wide
- ESLint and Prettier for consistent formatting
- Pre-commit hooks for quality gates
📈 Performance & Scalability
Caching Strategy
- Invoices: 60-120s per page; bust on WHMCS webhook
- Cases: 30-60s; bust after create/update
- Catalog: 5-15m; manual bust on changes
- Keys include user_id to prevent cross-user leakage
Database Optimization
- Connection pooling with Prisma
- Proper indexing on frequently queried fields
- Optional mirrors for external system data
This architecture supports clean, maintainable code with clear separation of concerns and production-ready security.