Skip to main content

Overview

To maintain domain type safety and eliminate duplicate code across the web application, mobile app, backend API, and worker processes, BrokerOS organizes domain logic into pure TypeScript packages under packages/. These packages are consumed by applications via Turborepo workspace protocol ("workspace:*"), ensuring compile-time safety and instant IDE navigation across package boundaries.

Package Integration Architecture


The 6 Core Packages

1. @brokeros/constants

Contains pure TypeScript constants, enums, UI colors, and pure normalizer functions. It is decomposed into domain sub-modules rather than a monolithic flat file:
  • roles.ts: The 14 official system roles (ROLES, ROLE_CODES), human-readable role labels (ROLE_LABELS), and department boundary helpers (isCpRole, isBrokerageRole, isManagementRole).
  • utils/phone.ts: Canonical phone normalization and sanitization utilities (normalizePhoneNumber, sanitizePhoneForMeta, normalizePhone, phonesMatch, isValidE164, phoneVariants).
  • crm/: Core CRM status badges and color maps:
    • lead.ts: Lead status configs (LEAD_STATUS_CONFIG), temperatures (LEAD_TEMPERATURE_CONFIG), and source labels.
    • inventory.ts: Unit statuses (UNIT_STATUS_CONFIG) and project status configurations.
    • booking.ts: Booking lifecycle statuses (BOOKING_STATUS_CONFIG), payment statuses, and loan stages.
    • broker.ts: Broker network statuses (BROKER_STATUS_CONFIG) and brokerage commission stages.
    • approvals.ts: Approval request statuses (APPROVAL_STATUS_CONFIG), site visit states, and negotiation stages.
  • voice/: Telephony carrier identifiers, AI agent platforms, voice catalog mappings, prompt templates, per-minute pricing tables, and the normalizeVoiceLeadVariables function.
  • whatsapp/: Meta template categories, message status codes, and 24-hour customer service window thresholds.
  • sms/: DLT operator entity mappings, encoding segment calculations (GSM-7 vs. UCS-2 Unicode).
  • email/: SMTP provider port configurations and tracking pixel parameter keys.
  • campaign.ts: Shared marketing broadcast status and channel enums.
  • export.ts: RFC-4180 CSV lead formatter (formatLeadsToCsv) and standalone responsive HTML report generator (generateAnalyticsHtmlReport).

2. @brokeros/types

Central repository for shared TypeScript interfaces, DTO definitions, and event payloads:
  • crm/: Core CRM domain types and transfer objects:
    • lead.ts: LeadDto, LeadListItemDto, LeadDetailsDto, LeadStatus, LeadTemperature, LeadSourceType.
    • booking.ts: BookingDto, BookingStatus, CustomerDto, CustomerDocumentDto, PaymentScheduleItemDto, LoanCaseDto.
    • inventory.ts: ProjectDto, TowerDto, FloorDto, UnitDto, UnitStatus, UnitType.
    • broker.ts: BrokerDto, BrokerStatus, BrokerMeetingDto, BrokerageRecordDto, BrokerageSettlementDto.
    • approvals.ts: ApprovalRequestDto, ApprovalStatus, ApprovalType, SiteVisitDto, NegotiationDto.
    • roles.ts: RoleCode, RoleDto, DepartmentDto, UserSummaryDto.
  • common.ts: Pagination queries, API response envelopes (ApiResponse<T>), and user session shapes.
  • voice/: Telephony payloads, agent webhook bodies, carrier streaming audio buffers.
  • whatsapp/: Meta Cloud API response types, interactive button tap payloads, and contact objects.
  • email.ts & sms.ts: Recipient CSV row schemas, tracking events, and delivery receipts.
  • export.ts: ExportLeadRecord, AnalyticsReportPayload, AnalyticsSummaryCard, AnalyticsFunnelStage, AnalyticsReportSection.

3. @brokeros/validators

Shared Zod schemas providing runtime validation for web forms, mobile inputs, and API request bodies:
  • PhoneSchema: Validates international E.164 phone formats (/^\+?[1-9]\d{6,14}$/).
  • CreateLeadSchema: Validates prospect name, phone, budget, temperature, and assigned project ID.
  • CreateCampaignSchema: Validates broadcast title, channel (EMAIL, SMS, VOICE, WHATSAPP), and audience sources.
  • SiteVisitVerificationSchema: Validates latitude, longitude, and selfie URLs for mobile check-ins.

4. @brokeros/prisma

The centralized database package housing the Prisma ORM schema, migrations, and generated client:
  • Schema file located at packages/prisma/schema.prisma.
  • Prisma client generated directly to packages/prisma/generated/client.
  • Exported via @brokeros/prisma for consumption by apps/api and apps/workers.
  • Applications import the singleton client instance: import { prismaClient } from '@brokeros/prisma'.

5. @brokeros/storage

Centralized wrapper for cloud object storage (Vercel Blob):
  • Provides uploadFileToBlob for streaming files, avatars, call recordings, and brochures.
  • Provides fetchBlobBuffer for secure server-side binary retrieval and streaming with automatic token injection.
  • Eliminates storage token leakage and raw HTTP calls from controllers.

6. @brokeros/messaging

Centralized, deep cross-channel message dispatch engine (SMS, Email, WhatsApp) providing atomic reservation, credential resolution, and provider dispatch across apps/api and apps/workers:
  • Atomic Reservation: Uses database-level conditional transitions (SCHEDULED -> PROCESSING) to eliminate double-send race conditions between background queue scanners and immediate API user actions.
  • Lazy Adapter Registries: Dynamically instantiates and caches provider adapters (Twilio, Gupshup, Sinch, SendGrid, Brevo, AWS SES, Meta Cloud API) on first use.
  • Resilient Fallback: Fetches stored database credentials, falling back to root environment variables when integrations are unconfigured.
  • In-place Status Lifecycle: Transitions message status directly (DELIVERED, SENT, FAILED) without deleting rows or breaking conversational audit trails.

Package Development Laws

All code placed in packages/ must adhere to strict architectural rules:
  1. Zero Side Effects: Packages must be pure TypeScript. Never import React, Next.js, or NestJS specific modules inside packages/.
  2. No Circular Dependencies: Packages must follow a strict hierarchy. For instance, @brokeros/validators may import @brokeros/types, but @brokeros/types must never import from @brokeros/validators.
  3. No Direct External Calls: Packages define interfaces and data shapes, not third-party SaaS HTTP callers. External network calls belong in integrations/.
  4. Gradual Migration: Migrate legacy types and constants out of apps/web/ and apps/mobile/ chunk by chunk into packages/ without sweeping breakages.