7.0 KiB
7.0 KiB
Customer Portal Project
A modern customer portal where users can self-register, log in, browse & buy subscriptions, view/pay invoices, and manage support cases.
Architecture Overview
Systems of Record
- WHMCS: Billing, subscriptions, and invoices
- Salesforce: CRM (Accounts, Contacts, Cases)
- Portal: Modern UI with backend for frontend (BFF) architecture
Identity Management
- Portal-native authentication (email + password, optional MFA)
- One-time WHMCS user verification with forced password reset
- User mapping:
user_id ↔ whmcs_client_id ↔ sf_contact_id/sf_account_id
Tech Stack
Frontend (Portal UI)
- Next.js 15 with App Router
- Turbopack for ultra-fast development and builds
- React 19 with TypeScript
- Tailwind CSS with shadcn/ui components
- TanStack Query for data fetching and caching
- Zod for validation
- React Hook Form for form management
Backend (BFF API)
- NestJS 11 (Node 24 Current or 22 LTS)
- Prisma 6 ORM
- jsforce for Salesforce integration
- WHMCS API client
- BullMQ for async jobs with ioredis
- OpenAPI/Swagger for documentation
Logging
- Centralized structured logging via Pino using
nestjs-pinoin the BFF - Sensitive fields are redacted; each request has a correlation ID
- Usage pattern in services:
- Inject
Loggerfromnestjs-pino:constructor(@Inject(Logger) private readonly logger: Logger) {} - Log with structured objects:
this.logger.error('Message', { error }) - See
docs/LOGGING.mdfor full guidelines
- Inject
Data & Infrastructure
- PostgreSQL 17 for users, ID mappings, and optional mirrors
- Redis 8 for cache and queues
- Docker for local development (Postgres/Redis)
Project Structure
projects/new-portal-website/
├── apps/
│ ├── portal/ # Next.js frontend (UI)
│ └── bff/ # NestJS backend (API)
├── tools/
│ ├── dev/ # Development scripts
│ └── deployment/ # Docker Compose for development
├── docs/ # Documentation
├── packages/ # Shared packages
└── secrets/ # Private keys (git ignored)
Getting Started
Prerequisites
- Node.js 24 (Current) or 22 (LTS)
- Docker and Docker Compose
- pnpm (recommended) via Corepack
Local Development Setup
-
Start Development Environment
# Option 1: Start everything at once (recommended) pnpm start:all # Option 2: Start services only, then apps manually pnpm start:services -
Setup Portal (Frontend)
cd apps/portal cp .env.example .env.local pnpm install pnpm run dev -
Setup BFF (Backend)
cd apps/bff # Choose your environment template: # cp .env.dev.example .env # for development # cp .env.production.example .env # for production cp .env.dev.example .env pnpm install pnpm run dev
Environment Variables
Portal (.env.local)
NEXT_PUBLIC_API_BASE="http://localhost:4000"
NEXT_PUBLIC_APP_NAME="Customer Portal"
BFF (.env)
DATABASE_URL="postgresql://app:app@localhost:5432/portal?schema=public"
REDIS_URL="redis://localhost:6379"
WHMCS_BASE_URL="https://<your-whmcs>"
WHMCS_API_IDENTIFIER="<identifier>"
WHMCS_API_SECRET="<secret>"
SF_LOGIN_URL="https://login.salesforce.com"
SF_CLIENT_ID="<consumer_key>"
SF_USERNAME="<integration@yourco.com>"
SF_PRIVATE_KEY_PATH="./secrets/sf.key"
BFF_PORT=4000
Data Model
Core Tables (PostgreSQL)
users- Portal user accounts with auth credentialsid_mappings- Cross-system user ID mappingsinvoices_mirror- Optional WHMCS invoice cachesubscriptions_mirror- Optional WHMCS service cacheidempotency_keys- Prevent duplicate operations
API Surface (BFF)
Authentication
POST /api/auth/signup- Create portal user → WHMCS AddClient → SF upsertPOST /api/auth/login- Portal authenticationPOST /api/auth/link-whmcs- OIDC callback or ValidateLoginPOST /api/auth/set-password- Required after WHMCS link
User Management
GET /api/me- Current user profileGET /api/me/summary- Dashboard summaryPATCH /api/me- Update profilePATCH /api/me/billing- Sync to WHMCS fields
Catalog & Orders
GET /api/catalog- WHMCS GetProducts (cached 5-15m)POST /api/orders- WHMCS AddOrder with idempotency
Invoices
GET /api/invoices- Paginated invoice list (cached 60-120s)GET /api/invoices/:id- Invoice detailsPOST /api/invoices/:id/sso-link- WHMCS CreateSsoToken
Subscriptions
GET /api/subscriptions- WHMCS GetClientsProducts
Support Cases (Salesforce)
GET /api/cases- Cases list (cached 30-60s)GET /api/cases/:id- Case detailsPOST /api/cases- Create new case
Webhooks
POST /api/webhooks/whmcs- WHMCS action hooks → update mirrors + bust cache
Frontend Pages
Initial Pages
/- Dashboard (next invoice due, active subs, open cases)/billing/invoices- Invoice list/billing/invoices/[id]- Invoice details/subscriptions- Active subscriptions/support/cases- Support cases list/support/cases/[id]- Case details/support/new- Create new case/account/profile- User profile management/account/security- Security settings/auth/login- Sign in/auth/signup- Create account/auth/set-password- Set password after WHMCS link
Development Milestones
Milestone 1: Identity & Linking
- Portal login/signup
- One-time WHMCS verification
- Set new portal password
- Store id_mappings
Milestone 2: Billing
- Product catalog (GetProducts)
- Checkout (AddOrder)
- Invoice list/detail (GetInvoices)
- WHMCS SSO deep links
Milestone 3: Cases & Webhooks
- Salesforce case list/create
- WHMCS webhooks → cache bust + mirrors
- Nightly reconcile job (optional)
Security Features
- HTTPS only with HttpOnly/SameSite cookies
- Optional MFA for portal accounts
- Idempotency keys on all mutating operations
- Row-level security (user must own resources)
- PII minimization with encryption at rest/in transit
- No WHMCS/SF credentials exposed to browser
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
Current Status
✅ Completed:
- Project structure setup
- Next.js 15 app with TypeScript
- Tailwind CSS with shadcn/ui
- TanStack Query configuration
- Docker Compose for PostgreSQL 17 and Redis 8
- Environment configuration
- Basic landing page
🚧 Next Steps:
- Set up NestJS backend (BFF)
- Implement authentication system
- Create database schema with Prisma
- Build initial API endpoints
Contributing
- Ensure Docker services are running
- Follow the coding standards (ESLint, Prettier)
- Write tests for new features
- Update documentation as needed
License
[Your License Here]