Skip to content

Architecture

Nexus is a Turborepo monorepo with 12 apps, 13 shared packages, and three product databases (plus Temporal’s internal store). See the System graph for the full dependency picture and the Network graph for traffic flow.

graph TD
    subgraph "Customer-facing"
        SM[site-main :3000]
        SS[site-shop :3010]
        SH[site-hypno :3020]
    end
    subgraph "Staff / ops"
        P[portal :3030\nadmin]
        PB[portal-business :3043\nbusiness owners]
        PBW[portal-business-web\nCaddy proxy]
    end
    subgraph "API servers"
        SA[scheduler-api :4000\nFastify · tRPC · Temporal]
        VS[vendure-server :3001\nNestJS GraphQL]
        D[directus :8055\nHeadless CMS]
    end
    subgraph "Workers"
        SW[scheduler-worker]
        VW[vendure-worker]
    end

    SM & SS & SH --> SA
    SM & SS & SH --> VS
    SM & SS & SH --> D
    P --> SA
    PBW --> PB
    PB --> SA
    SW --> SA
    VW --> VS

Scheduler (scheduler-api + scheduler-worker)

Section titled “Scheduler (scheduler-api + scheduler-worker)”

The core platform: bookings, business management, billing, provisioning, notifications, chat. Fastify + tRPC on the API side; BullMQ + Temporal for async work. Drizzle ORM on PostgreSQL (Neon).

Commerce (vendure-server + vendure-worker)

Section titled “Commerce (vendure-server + vendure-worker)”

Headless commerce layer: product catalog, cart, checkout, orders. NestJS + GraphQL. TypeORM on PostgreSQL (Neon). Kept in sync with the scheduler via convergence workflows.

Headless CMS for tenant content (pages, blog, media). Multi-tenancy via a custom WorkOS OIDC extension that maps WorkOS org → Directus role on login. PostgreSQL (Neon) + Cloudflare R2.

Layer Package(s) Consumed by
Contracts (source of truth) @nexus/scheduler-contracts server, SDK, tRPC client
Public SDK @nexus/scheduler-sdk, @nexus/vendure-sdk, @nexus/directus-sdk sites, business-client
Customer client @nexus/business-client sites
Admin client @nexus/scheduler-client, @nexus/scheduler-platform-client portals, e2e tests
Auth @nexus/auth-client, @nexus/workos-auth portals, scheduler-api, directus
Events @nexus/platform-events scheduler-api, workers
UI @nexus/ui (shadcn + Radix + Tailwind) all React apps
Infra @nexus/registrar, @nexus/shared-types scheduler-api, IaC
Store Provider (prod) Provider (local) Used by
Scheduler PostgreSQL Neon Docker :5434 scheduler-api, scheduler-worker
Vendure PostgreSQL Neon Docker :5432 vendure-server, vendure-worker
Directus PostgreSQL Neon Docker :5433 directus
Temporal PostgreSQL Railway managed temporal-server
Redis Railway managed Docker :6379 BullMQ (all), sessions, SSE bridge
Object storage Cloudflare R2 MinIO Docker :9000 vendure (assets), directus (media), scheduler (chat)

Public / contract-first — customer-facing, slug-scoped (/api/public/:slug/*). Zod schemas in @nexus/scheduler-contracts are the single source of truth. A drift between client and server is a runtime 500, not a silent type mismatch.

Admin / tRPC — portal-facing (/trpc/*). End-to-end type-safe: types are inferred from the server AppRouter, never hand-written on the client. Consumed by both portal (via @nexus/scheduler-client) and portal-business.

Long-running multi-system operations (provisioning, convergence, wipe) run as Temporal workflows hosted on Railway. The Temporal worker is embedded in scheduler-api. See Temporal cluster.

All production services run on Railway (single environment). DNS is on Cloudflare. Infrastructure is managed as code via Pulumi TypeScript in infra/, with R2 as the Pulumi state backend. CI automatically runs pulumi up on merge when infra/ changes.

See Environments concept for stack details and CI graph for the full pipeline.