This section is the orientation for engineers new to the system. It defines the three actors, the network topology, and the key concepts the rest of the document assumes.
System overview (Mermaid)
flowchart LR
subgraph CP["CoachPilot platform (Exoscale SKS · Zurich)"]
direction TB
GW[api.coachpilot.ch<br/>FastAPI gateway]
DASH[app.coachpilot.ch<br/>Admin dashboard]
QUIZ[quiz.thesynergygroup.ch<br/>Public quiz Next.js]
AGENT[adaptive-assessment agent<br/>Python · NATS]
PG[(Postgres<br/>framework_configs<br/>tenant_brand<br/>assess_sessions)]
REDIS[(Redis)]
NATS((NATS bus))
GW --- PG
DASH --- GW
QUIZ --- GW
AGENT --- NATS
GW --- NATS
AGENT --- PG
QUIZ --- REDIS
end
TSG[TSG visitors] -->|direct| QUIZ
MMC_USER[MMC visitors] -->|"WP page<br/>(iframes Mirror/Game/Deal/Realm,<br/>natively serves Likert)"| WP[mindfulmoneycoaching.online<br/>WordPress]
WP -. iframe<br/>quiz.tsg/?tenant=mmc .-> QUIZ
WP -. POST scores .-> GW
GW -. read bio+history .-> WP
classDef platform fill:#e3f2fd,stroke:#1976d2
classDef tenant fill:#fff3e0,stroke:#f57c00
classDef external fill:#f3e5f5,stroke:#7b1fa2
class CP,GW,DASH,QUIZ,AGENT,PG,REDIS,NATS platform
class WP tenant
class TSG,MMC_USER external
Three actors, one cluster
┌──────────────────────────────────────────────────────────────────────────┐
│ │
│ CoachPilot (Exoscale SKS — Zurich) │
│ │
│ ┌──────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ api.coachpilot │ │ app.coachpilot │ │ quiz.thesynergy │ │
│ │ .ch (gateway) │ │ .ch (dashboard) │ │ group.ch │ │
│ │ FastAPI/Python │ │ Next.js 14 │ │ Next.js public │ │
│ └────────┬─────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
│ ├──────────────────────┼─────────────────────┤ │
│ │ │ │
│ ┌────────▼──────────┐ ┌──────────────┐ ┌─────────▼──────┐ │
│ │ Postgres (RDS) │ │ Redis │ │ NATS bus │ │
│ │ framework_configs│ │ sessions │ │ agent traffic │ │
│ │ tenant_brand │ │ cache │ │ │ │
│ │ assess_sessions │ │ │ │ │ │
│ └───────────────────┘ └──────────────┘ └────────┬───────┘ │
│ │ │
│ ┌────────▼─────────┐ │
│ │ adaptive- │ │
│ │ assessment agent │ │
│ │ (Python, NATS) │ │
│ └──────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
▲ ▲
│ /api/v1/assess/* (gateway is public-readable) │
│ │
┌──────────┴───────────────┐ ┌────────────────┴──────────┐
│ TSG visitors │ │ MMC visitors │
│ → quiz.thesynergy │ │ → mindfulmoneycoaching │
│ group.ch directly │ │ .online/money-quiz/ │
│ │ │ (WP page with iframe │
│ │ │ to quiz.tsg/?tenant=mmc│
│ │ │ for Mirror/Game/Deal/ │
│ │ │ Realm; legacy Likert │
│ │ │ is native WP) │
└──────────────────────────┘ └───────────────────────────┘
| Actor | What they are | Domain | Owner |
|---|---|---|---|
| CoachPilot | The SaaS platform — gateway, dashboard, agent, DB, NATS | coachpilot.ch (apex marketing) + api.coachpilot.ch / app.coachpilot.ch (infra) | The Synergy Group |
| TSG | A tenant AND the canonical public quiz frontend host | quiz.thesynergygroup.ch, assess.thesynergygroup.ch | The Synergy Group |
| MMC | A tenant (Ilana Jankowitz's coaching practice) that hosts quizzes on her own WordPress | mindfulmoneycoaching.online | Mindful Money Coaching |
Key insight: there is no separate "MMC infrastructure" or "TSG infrastructure." There is one platform running one set of pods. Tenancy is a per-row concern in the database, surfaced via the ?client=<tenant> query parameter or Host header.
The five Money Quiz formats
Canonical IDs and where each is hosted:
| ID (canonical) | Display | Where it runs | Where it's served |
|---|---|---|---|
likert | Money Quiz | MMC WordPress (PHP, 112 traits) | mindfulmoneycoaching.online/money-quiz/ |
qa | Money Mirror | moneyquiz-app Next.js | quiz.thesynergygroup.ch/ (Mirror is the default landing today) |
game | Money Game | moneyquiz-app Next.js | quiz.thesynergygroup.ch/game |
deal | Money Deal | moneyquiz-app Next.js | quiz.thesynergygroup.ch/deal |
realm | Money Realm | moneyquiz-app Next.js (shares Deal engine) | quiz.thesynergygroup.ch/realm |
For non-TSG tenants like MMC, the four newer formats are iframed in at tenant-controlled URLs:
mindfulmoneycoaching.online/money-mirror/mindfulmoneycoaching.online/money-game/mindfulmoneycoaching.online/money-deal/mindfulmoneycoaching.online/money-realm/
A WordPress mu-plugin (auto-pages.php) creates and renders these iframe pages. The Legacy Likert format (/money-quiz/) is a native WordPress page, not an iframe.
See 03 Format taxonomy for the full alias map, deployment history, and naming rationale.
Two patterns of quiz hosting
A tenant chooses ONE of two patterns at onboarding. The choice is encoded in tenant_brand.slug_prefix:
| Pattern | slug_prefix value | URL example | When to use |
|---|---|---|---|
| Platform-hosted (direct) | '' (empty) | quiz.thesynergygroup.ch/mirror | Tenant has no existing marketing site; or wants a dedicated subdomain |
| Tenant-hosted (iframe) | non-empty (e.g. money-) | mindfulmoneycoaching.online/money-mirror/ | Tenant has an existing site with SEO equity / brand recognition |
Today: TSG, CoachPilot, HSP use the direct pattern. MMC uses the iframe pattern.
See 02 Tenancy model §Per-tenant URLs for the composer logic.
Repository layout
StarGate/ (working tree root)
├── 10 Projects/
│ ├── MoneyQuiz/
│ │ ├── moneyquiz-app/ (public quiz Next.js app)
│ │ │ └── src/...
│ │ ├── Personas/ (Tier-2/3 evaluation harness)
│ │ ├── QUIZ_DESIGN_STRATEGY.md (scoring + calibration design notes)
│ │ └── docs/ (this directory)
│ │ └── architecture/
│ ├── Agentic Starter/ (CoachPilot platform repo)
│ │ ├── api-gateway/ (FastAPI Python)
│ │ │ ├── routers/
│ │ │ ├── registry/
│ │ │ ├── migrations/
│ │ │ └── scoring_calibration.py
│ │ ├── dashboard/ (Next.js admin)
│ │ │ └── src/app/[locale]/portal/tenant/brand/
│ │ └── infra/
│ ├── Agent Zero/repos/agent-zero-agents/
│ │ └── agents/adaptive-assessment/ (Python NATS agent)
│ │ ├── quiz_engine.py
│ │ ├── scoring_calibration.py
│ │ └── framework_definitions/
│ │ └── money_archetypes.json
│ └── MMC/ (Ilana's WordPress)
│ ├── coachpilot-theme-v2/
│ ├── sg-course-engine/ (mu-plugin)
│ │ ├── api/archetype-scores.php
│ │ └── admin/page-quiz-leads.php
│ └── mu-plugins/
│ ├── mmc-mq-ab-variant.php
│ └── mmc-moneyquiz-bridge/
│ └── auto-pages.php
Key concepts
Resolved framework
The "resolved framework" is the merged result of:
- The platform default JSON (
framework_definitions/money_archetypes.json) - The tenant's override row in
framework_configs
Consumers fetch via GET /api/v1/assess/framework/{id}/resolved?client=<tenant>. The result includes everything a consumer needs: dimensions, scoring engine, voice, modes, landing copy, communications, results display, providers. Cached for 30 seconds at the Next.js fetch layer.
See 05 Configuration flow for the PATCH → resolve cycle.
Tier-2 calibration
A rule engine in framework.scoring.engine.archetype_calibration.rules that adjusts raw archetype scores based on co-occurrence conditions. The platform default rule victim_martyr_cooccurrence lifts Tier-2 bio-recall from 0.646 → 0.875 by catching Martyr signals that sit just below the top-3 cutoff when Victim is strong.
Applied in three places, all of which must produce identical outputs:
score-analyser.ts::applyArchetypeCalibration(TS, used by Mirror + Game)agents/adaptive-assessment/scoring_calibration.py::apply_archetype_calibration(Python, used by Deal + Realm via the agent)api-gateway/scoring_calibration.py::apply_archetype_calibration(Python, used by MMC WP Likert via the/calibratebridge)
Per-tenant brand
The tenant_brand table stores per-tenant white-label identity:
- Coach name, photo, title, email (sender + notification recipient)
- Brand colours, fonts, logo URL
slug_prefix+canonical_quiz_url(URL composition)archetype_scores_webhook+archetype_scores_secret(external CRM)analytics_webhook(per-tenant event sink)
The public quiz app reads the brand server-side in layout.tsx via resolveTenantFromHeaders + loadTenantBrandById and threads it through:
<TenantThemeProvider>— emits CSS custom-property overrides as a<style>block (Tailwind v4's@theme inlinereads these at runtime).<TenantBrandProvider>— React context for client components like BookingCTA.
See 07 Quiz app runtime.
Dual analytics
The system has TWO independent analytics surfaces:
-
MMC WordPress Quiz Leads (wp-admin → MMC Marketing → Quiz Leads) — Ilana's primary customer-facing view. Receives a webhook on every quiz completion (every format, every tenant that has
archetype_scores_webhookset), stores inmq_*legacy tables, fires emails, drives the Prospects/Campaigns/Tracking tabs. The A/B Tests tab queries GA4 directly. -
CoachPilot platform
/admin/analytics— aggregate KPIs across all tenants. Sourced fromassess_sessionsin Postgres. No per-tenant Sessions drilldown yet (deferred).
See 08a MMC analytics and 08b Platform analytics.
What's not covered here
- Premium card-game economics (
deal/premium/*) — see moneyquiz-app/src/app/api/deal/premium/ - Personas (Tier-2/3 evaluation harness) — see Personas/README.md (TODO: write README)
- ElevenLabs voice configuration — provider-specific docs in 12 Security
- The Agent Zero orchestrator pattern beyond
adaptive-assessment— see Agent Zero/CLAUDE.md
Next
→ 02 Tenancy model — how slug_prefix works, override layers, theme provider.