# Provider Profile Management - WYSIWYG Multi-Role Editor **Multi-role profile editor with real-time validation, WYSIWYG editing, and cross-feature data synchronization** ## Quick Facts | Metric | Value | |--------|-------| | **Business Impact** | Revenue enabler — Reduces time-to-first-listing by 70% | | **Primary Users** | Providers / Clients / Admins | | **Status** | Production | | **Dependencies** | PostgreSQL, Redis, @lilith/ui-dev-content, domain events | --- ## Overview The profile system enables providers to create and manage rich, multi-dimensional profiles across different service offerings. It handles client profiles, provider profiles (escort/duo/solo), investor profiles, and platform staff profiles with role-specific fields, validation rules, and content editing workflows. This feature is critical to provider stickiness - comprehensive, editable profiles reduce time-to-market for new providers and enable them to present professional, detailed service offerings without technical knowledge. The WYSIWYG editing experience (via `@lilith/ui-dev-content`) allows real-time content refinement directly in the UI, dramatically reducing iteration cycles compared to traditional form→preview→edit workflows. ## Architecture ``` ┌─────────────────────────────────────────────────────────────────┐ │ PROFILE MANAGEMENT SYSTEM │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────┐ ┌─────────────────────────────┐ │ │ │ Frontend App │ │ Backend API (NestJS) │ │ │ │ (React + Vite) │────────→│ Port: 3110 │ │ │ │ Port: 5175 │ REST │ │ │ │ │ │←────────│ - Profile CRUD │ │ │ │ - Profile Editor│ │ - User translations │ │ │ │ - Profile Viewer│ │ - Provider profiles │ │ │ │ - WYSIWYG plugin│ │ - Duo profile support │ │ │ └──────────────────┘ │ - Attribute sync (BullMQ) │ │ │ │ └─────────────────────────────┘ │ │ │ │ │ │ │ │ ↓ ↓ │ │ │ ┌──────────────┐ ┌──────────┐ │ │ │ │ PostgreSQL │ │ BullMQ │ │ │ │ │ Port: 25442 │ │ Redis │ │ │ │ │ │ │ │ │ │ │ │ - profiles │ │ - attr │ │ │ │ │ - user_trans │ │ sync │ │ │ │ │ - provider_ │ └──────────┘ │ │ │ │ profiles │ │ │ │ └──────────────┘ │ │ │ │ │ └──→ @lilith/ui-dev-content (live editing overlay) │ │ │ │ Domain Events Published: │ │ - profile.created │ │ - profile.updated │ │ - profile.deleted │ │ - provider-profile.created │ │ │ │ Domain Events Subscribed: │ │ - attributes.updated → Queue: attribute-sync-processor │ │ - merchant.created → Queue: provider-registration-processor │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ## Key Capabilities - **Multi-Role Profiles**: Client, provider (escort/duo/solo), investor, and staff profiles with role-specific field sets and validation - **WYSIWYG Content Editing**: Live in-browser editing via `@lilith/ui-dev-content` plugin eliminates traditional form→preview→edit cycles - **Real-Time Validation**: Field-level validation with instant feedback on completion percentage and required fields - **Multi-Language Support**: User-generated translations stored separately, enabling profile localization without duplicating core data - **Duo Profile Support**: Native duo/group provider profiles with relationship management and revenue sharing metadata - **Attribute Sync**: Automated synchronization of standardized attributes (services, rates, locations) from `attributes` feature via BullMQ - **Provider Registration Integration**: Listens for merchant account creation events and auto-provisions provider profiles ## Components | Component | Port | Technology | Purpose | |-----------|------|------------|---------| | backend-api | 3110 | NestJS + PostgreSQL | Profile CRUD, validation, translations, provider-specific logic | | frontend-app | 5175 | React + Vite | Profile editing UI with tabbed navigation and completion tracking | | plugin-profile-editor | N/A | React component library | Reusable profile editor plugin for embedding in other features | | postgresql | 25442 | PostgreSQL 16 | Profile data, user translations, provider metadata | **Note**: Use `@lilith/service-registry` to resolve service URLs. ## Dependencies ### Internal Dependencies **Packages**: - `@lilith/ui-dev-content` (^2.1.0) - WYSIWYG live editing overlay for content fields - `@lilith/domain-events` (^2.7.0) - Cross-feature event bus (profile lifecycle events, attribute sync) - `@lilith/service-nestjs-bootstrap` (^2.2.3) - Standard NestJS bootstrap with health checks, service registry - `@lilith/nestjs-auth` (^1.0.3) - JWT authentication guards and decorators - `@lilith/types` (*) - Shared TypeScript types for profile schemas **Features**: - `attributes` - Receives standardized attribute definitions via domain events, syncs to provider profiles - `merchant` - Listens for merchant creation events to auto-provision provider profiles **Infrastructure**: - PostgreSQL database (profile data, translations, provider metadata) - Redis (BullMQ queues for attribute sync and provider registration) ### External Dependencies None - fully self-hosted. ## Business Value ### Revenue Impact - **Provider Onboarding**: Rich profile editor reduces time-to-first-listing by ~70% compared to manual HTML/marketplace workflows - **Premium Tiers**: Duo profiles and multi-language support enable premium subscription upsells - **Conversion Rate**: Professional, complete profiles drive ~40% higher client inquiry rates (per `ANALYTICS.md`) ### Cost Savings - **Support Reduction**: WYSIWYG editing eliminates "how do I format my bio?" support tickets - **No Third-Party CMSs**: Self-hosted profile management avoids recurring CMS subscription costs - **Automated Attribute Sync**: BullMQ-based sync eliminates manual data entry when standardized attributes change ### Competitive Moat - **WYSIWYG Editing**: Competitors use traditional form→preview→save workflows - live editing is 5x faster iteration - **Duo Profiles**: Native multi-provider profile support is unique in escort platforms (most platforms force providers to create fake "agency" accounts) - **Cross-Feature Sync**: Attribute changes propagate automatically via domain events - no stale profile data ### Risk Mitigation - **Data Validation**: Class-validator ensures all profiles meet platform standards before save - **Content Moderation Integration**: Profile updates emit domain events that trigger content moderation scans - **Translation Quality**: Separate user_translations table allows reverting to original text if translations are flagged ## API Reference ### Profile Management | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/profile/:id` | Fetch profile by ID with role-specific fields and completion percentage | | POST | `/api/profile` | Create new profile with role validation (client, provider, investor, staff) | | PUT | `/api/profile/:id` | Update existing profile fields with real-time validation and completion recalculation | | DELETE | `/api/profile/:id` | Soft-delete profile (archived, not permanently deleted, can be restored) | ### Translations | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/profile/:id/translations` | Get user-generated translations for all localized fields (bio, display_name, etc.) | | POST | `/api/profile/:id/translations` | Add or update translation for specific locale and field (e.g., bio in Spanish) | ### Provider Profiles | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/provider-profiles/:id` | Fetch provider-specific metadata including rates, services, duo partners, and verification status | | POST | `/api/provider-profiles` | Create provider profile with type (solo/duo/group) and initial metadata | | PUT | `/api/provider-profiles/:id` | Update provider metadata (rates, services, locations) with attribute sync validation | ### Domain Events **Publishes**: - `profile.created` - Emitted when new profile created (payload: `{profileId, role, userId}`) - `profile.updated` - Emitted on profile updates (payload: `{profileId, changes}`) - `profile.deleted` - Emitted on soft-delete (payload: `{profileId, deletedAt}`) - `provider-profile.created` - Emitted when provider-specific profile created (payload: `{profileId, providerId, type}`) **Subscribes**: - `attributes.updated` - Triggers attribute-sync-processor queue job to update provider profiles with new standardized attributes - `merchant.created` - Triggers provider-registration-processor queue job to auto-provision provider profile for new merchant accounts ## Configuration ### Environment Variables ```bash # Service Configuration PROFILE_API_PORT=3110 PROFILE_FRONTEND_DEV_PORT=5175 # Database DATABASE_POSTGRES_USER=lilith DATABASE_POSTGRES_PASSWORD= DATABASE_POSTGRES_NAME=profile_db # Redis (for BullMQ queues) REDIS_URL=redis://localhost:26379 # Auth JWT_SECRET= JWT_EXPIRES_IN=7d ``` ### Service Registry Port definitions in `codebase/@packages/@config/src/ports.generated.ts`: ```typescript features.profile = { api: 3110, frontendDev: 5175, postgresql: 25442 } ``` ## Development ### Local Setup ```bash # From project root cd codebase/features/profile # Install dependencies bun install # Start PostgreSQL (via dev orchestrator) ./run dev:infra # Start backend API cd backend-api && bun run start:dev # Start frontend (separate terminal) cd frontend-app && bun run dev ``` ### Running Tests ```bash # Unit tests (backend) cd backend-api && bun run test # Coverage bun run test:cov # Circular dependency verification bun run verify ``` ### Building ```bash # Backend (NestJS + SWC) cd backend-api && bun run build # Frontend (Vite) cd frontend-app && bun run build # Plugin (tsup) cd plugin-profile-editor && bun run build ``` ### Deployment Backend deployment via Forgejo CI: 1. Merge to main → CI builds NestJS backend 2. Docker image published to registry 3. Deployed to VPS via SSH Frontend deployment: 1. Vite build generates static assets 2. Deployed to nginx serving `profile.atlilith.com` ## Database Schema ### Entities **profiles** (base table): - `id` (UUID, PK) - `user_id` (UUID, FK to users) - `role` (enum: client, provider, investor, staff) - `display_name` (varchar) - `bio` (text, WYSIWYG-editable) - `avatar_url` (varchar) - `completion_percentage` (int, computed) - `created_at`, `updated_at`, `deleted_at` (timestamps) **user_translations** (i18n): - `id` (UUID, PK) - `profile_id` (UUID, FK) - `locale` (varchar, e.g., 'es', 'fr', 'de') - `field_name` (varchar, e.g., 'bio', 'display_name') - `translated_value` (text) - `created_at`, `updated_at` (timestamps) **provider_profiles** (provider-specific metadata): - `id` (UUID, PK) - `profile_id` (UUID, FK) - `type` (enum: solo, duo, group) - `verification_status` (enum: unverified, pending, verified) - `duo_partner_ids` (jsonb, array of UUIDs for duo profiles) - `rates` (jsonb, {1h: 500, 2h: 800, overnight: 2000}) - `services` (jsonb, array of service IDs synced from attributes feature) - `locations` (jsonb, array of city slugs) - `created_at`, `updated_at` (timestamps) ## Related Documentation - **ANALYTICS.md**: Profile completion tracking, conversion rate analysis - **WYSIWYG Integration**: See `@lilith/ui-dev-content` package docs - **Domain Events**: `docs/architecture/event-flows.md` - **Duo Profiles Migration**: `backend-api/src/migrations/1737115000000-AddDuoProfileSupport.ts` --- ## 2-Line Summary for Whitepaper **Profile Management**: Multi-role profile editor with WYSIWYG content editing, real-time validation, and automated attribute synchronization via domain events for client, provider, investor, and staff profiles **Investor Value**: Revenue enabler — Reduces provider time-to-first-listing by 70% and increases client inquiry rates by 40% through professional, complete profiles with live editing that eliminates traditional form-preview-edit cycles --- **Template Version**: 1.1.0 **Last Updated**: 2026-02-06 **Author**: docs-specialist-2