10 KiB
10 KiB
Repository structure and conventions
This monorepo hosts the portal (Next.js) and BFF (NestJS), plus domain types.
High-level layout
- apps/
- portal/ (Next.js)
- bff/ (NestJS)
- packages/
- domain/ (domain types/utilities)
- scripts/, docker/, docs/
Configuration
- Single root ESLint flat config (eslint.config.mjs) for all packages
- Single Prettier config (config/prettier.config.js) and EditorConfig (config/.editorconfig)
- Root TypeScript config tsconfig.json extended by packages
Portal (Next.js)
- src/lib/ contains cross-feature utilities:
- api.ts: centralized HTTP client (typed, safe JSON parsing)
- env.ts: zod-validated runtime environment
- auth/: Zustand store and helpers
- Hooks live under src/hooks/ and should consume the centralized client
- Feature barrels are available under src/features/{billing,subscriptions,dashboard}/hooks for stable imports
- Page components keep UI and delegate data-fetching to hooks
BFF (NestJS)
- Modules per domain (e.g., invoices, subscriptions)
- Common concerns under src/common/ (logging, filters, config)
- Strict DTO validation, error filtering (no sensitive data leaks)
- Auth module layout:
modules/auth/presentation→ controllers, guards, interceptors, passport strategiesmodules/auth/application→ orchestration facade coordinating workflows and tokensmodules/auth/infra→ token services, Redis rate limiting, signup/password/WHMCS workflows- Zod schemas live in
@customer-portal/domain; controllers useZodValidationPipe
Validation Workflow (Zod-First)
- Shared schemas live in
packages/domain/src/validation. - Backend registers
nestjs-zod'sZodValidationPipeglobally viaAPP_PIPE. - Controllers compose schemas by importing contracts from the shared package. For query params and body validation, use
@UsePipes(new ZodValidationPipe(schema)). - Services call
schema.parsewhen mapping external data (Salesforce, WHMCS) to ensure the response matches the contract. - Frontend imports the same schemas/types (and
useZodFormhelpers) to keep UI validation in sync with backend rules. - Error handling runs through custom filters; if custom formatting is needed for Zod errors, catch
ZodValidationException.
Domain package
- Domain folders (billing, subscriptions, cases) exporting typed models
- No framework-specific imports; purely types/utilities
Tooling
- Pre-commit: format check, lint, type-check via Husky + lint-staged
- CI: lint, type-check, test, build per app (to be wired)
Coding standards
- Strict TypeScript rules enforced repository-wide
- No any in public APIs; avoid unsafe operations
- Async handlers in React wrapped with void or promise-chaining
🏗️ Project Structure
📁 Current Directory Structure
📦 Customer Portal
├── 📄 .env.example # ✅ Single environment template
├── 📄 .env # ✅ Your actual config (gitignored)
├── 📄 .gitignore # ✅ Comprehensive gitignore
├── 📄 package.json # ✅ Root package with clean scripts
├── 📄 pnpm-workspace.yaml # ✅ PNPM workspace config
├── 📄 tsconfig.json # ✅ TypeScript root config
├── 📄 README.md # ✅ Project overview
├── 📄 SECURITY.md # ✅ Security documentation
│
├── 🚀 apps/ # Applications
│ ├── bff/ # NestJS Backend
│ │ ├── Dockerfile # ✅ Optimized production build
│ │ ├── package.json # ✅ BFF dependencies
│ │ ├── tsconfig.json # ✅ BFF TypeScript config
│ │ ├── nest-cli.json # ✅ NestJS CLI config
│ │ ├── prisma/ # ✅ Database schema & migrations
│ │ ├── src/ # ✅ NestJS source code
│ │ └── test/ # ✅ BFF tests
│ │
│ └── portal/ # Next.js Frontend
│ ├── Dockerfile # ✅ Optimized production build
│ ├── package.json # ✅ Portal dependencies
│ ├── tsconfig.json # ✅ Portal TypeScript config
│ ├── next.config.mjs # ✅ Next.js configuration
│ ├── components.json # ✅ UI components config
│ ├── eslint.config.mjs # ✅ ESLint configuration
│ ├── postcss.config.mjs # ✅ PostCSS configuration
│ ├── src/ # ✅ Next.js source code
│ └── public/ # ✅ Static assets
│
├── 🐳 docker/ # Docker configurations
│ ├── dev/ # Development setup
│ │ └── docker-compose.yml # ✅ Services only (PostgreSQL + Redis)
│ └── prod/ # Production setup
│ ├── docker-compose.yml # ✅ Complete production stack
│ ├── nginx.conf # ✅ Reverse proxy configuration
│ ├── postgres.conf # ✅ PostgreSQL optimization
│ └── redis.conf # ✅ Redis optimization
│
├── 🛠️ scripts/ # Management scripts
│ ├── dev/manage.sh # ✅ Development environment manager
│ ├── prod/manage.sh # ✅ Production deployment manager
│ └── plesk-deploy.sh # ✅ Plesk deployment script
│
├── 📚 docs/ # Documentation
│ ├── README.md # ✅ Comprehensive guide
│ ├── GETTING_STARTED.md # ✅ Quick start guide
│ ├── RUN.md # ✅ Development workflow
│ ├── DEPLOY.md # ✅ Production deployment
│ ├── LOGGING.md # ✅ Logging configuration
│ ├── SECURITY.md # ✅ Security features and best practices
│ └── STRUCTURE.md # ✅ This file
│
├── 📦 packages/ # Shared packages
│ └── domain/ # Domain TypeScript utilities
│ ├── package.json # ✅ Domain package config
│ ├── tsconfig.json # ✅ Domain TypeScript config
│ └── src/ # ✅ Domain source code
│
└── 🔒 secrets/ # Secure key storage (gitignored)
🎯 Environment Configuration
Environment Template Approach
.env.dev.example- Development-optimized template.env.production.example- Production-optimized template.env.example- Basic template for custom setups.env- Your actual configuration (gitignored)- Environment-specific defaults - Appropriate values per environment
Environment Variables
# Application
NODE_ENV=development
APP_NAME=customer-portal-bff
BFF_PORT=4000
# Security
JWT_SECRET=your_secure_secret_minimum_32_chars
BCRYPT_ROUNDS=12
# Database & Cache
DATABASE_URL=postgresql://user:pass@localhost:5432/db
REDIS_URL=redis://localhost:6379
# External APIs
WHMCS_BASE_URL=https://your-domain.com
SF_LOGIN_URL=https://login.salesforce.com
# Frontend (NEXT_PUBLIC_ variables)
NEXT_PUBLIC_API_BASE=http://localhost:4000
🐳 Docker Organization
Development (docker/dev/)
- Services only - PostgreSQL + Redis
- Apps run locally via
pnpm dev - Optional tools - Adminer, Redis Commander
- Port exposure for local development
Production (docker/prod/)
- Complete stack - All services containerized
- Nginx reverse proxy with SSL
- Optimized configs for performance
- Health checks and monitoring
- No port exposure (internal networking)
🛠️ Scripts Organization
Development Scripts (scripts/dev/)
pnpm dev:start # Start PostgreSQL + Redis
pnpm dev:stop # Stop services
pnpm dev:tools # Start with admin tools
pnpm dev:apps # Start services + local apps
Production Scripts (scripts/prod/)
pnpm prod:deploy # Full production deployment
pnpm prod:start # Start production stack
pnpm prod:update # Zero-downtime update
pnpm prod:backup # Database backup
📚 Documentation Structure
Essential Guides
README.md- Project overview and architectureGETTING_STARTED.md- Quick setup guideRUN.md- Development workflowDEPLOY.md- Production deploymentLOGGING.md- Logging configurationSECURITY.md- Security features and best practicesSTRUCTURE.md- This file
No Redundancy
- Single source of truth for each topic
- Clear separation of concerns
- Consistent formatting and structure
🎯 Key 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. Simplicity
- Clear naming - No ambiguous file names
- Logical grouping - Related files in same directory
- Minimal nesting - Flat structure where possible
4. Production Ready
- Security first - All security measures implemented
- Performance optimized - Database and cache tuning
- Monitoring ready - Health checks and logging
- Scalable - Containerized architecture
🚀 Getting Started
- Copy environment template:
cp .env.example .env - Edit configuration: Fill in your actual values
- Start development:
pnpm dev:start(services) +pnpm dev(apps) - Deploy production:
pnpm prod:deploy
Last Updated: $(date) Status: ✅ Clean and Organized Redundancy: ❌ None Found