Developer DocsArchitecture

Architecture

PlaylogiQ is a Turborepo monorepo of Next.js apps and shared TypeScript packages, on a self-hosted Supabase (PostgreSQL + RLS) with a BullMQ worker.

System shape

                    ┌────────────────────────────── Caddy (HTTPS, per-subdomain) ──┐
                    │                                                               │
   Operator  ─────► apps/web    (dashboard)  ─┐                                     │
   Player    ─────► apps/player (portal)     ─┤                                     │
   PAM / SDK ─────► apps/api    (REST v1)     ─┼──► Supabase ── PostgreSQL + RLS     │
                    apps/docs   (this site)   ─┘        │   ── Auth (GoTrue)         │
                                                        │   ── Realtime              │
                                                        │   ── Storage               │
                    apps/worker (BullMQ) ◄── Redis ◄────┘                            │
                    └── drains: notifications · gamification · journeys · webhooks ──┘
  • apps/web — operator dashboard (App Router). Talks to Supabase directly (under RLS) and to the API.
  • apps/player — player-facing portal (App Router).
  • apps/api — public REST API under /api/v1 (App Router route handlers).
  • apps/docs — this documentation (Nextra).
  • apps/worker — a headless BullMQ worker draining queues over Redis.

Data flow (event-driven)

PAM ──POST /api/v1/events──► ingestion ──mapping──► player_events (append-only)

                                              BullMQ jobs (worker)

             ┌───────────────┬───────────────┬───────────┴───────────┐
        derive stats    advance lifecycle  recompute segments     run journeys
     (profiles, GGR…)   (stage + history)  (dynamic membership)   (enrol/step)
  • Append-only streams. player_events and balance_transactions are never updated or deleted — they are the source of truth; everything else is derived.
  • Idempotent ingestion. Events carry an optional event_id; re-sends are de-duplicated (see Event ingestion).

Multi-tenancy & security

Every brand-scoped table carries tenant_id and brand_id, and Row-Level Security enforces isolation in the database — not merely in app code. See Database & RLS and RBAC & permissions.

Real-time

Supabase Realtime powers live dashboards, leaderboards, and the player’s in-app inbox (fanned out from worker writes).

Where to go next