← Back to index | ← 02 Tenancy model | 04 Config schema →

The five canonical Money Quiz formats, their IDs, slugs, URLs, aliases, scoring paths, and how to add a new one. Reflects the post-rename state as of 2026-05-18 (C-phase complete).


The five canonical formats

Canonical IDDisplay nameBare slugWhat it isScoring engine
likertMoney Quizquiz112-trait Likert questionnaire on Ilana's WordPressWP PHP → gateway /calibrate
qaMoney MirrormirrorQ&A conversation with adaptive question selectionTS analyseScores
gameMoney Gamegame6-round card-flip gameTS analyseScores (gameMode)
dealMoney Dealdeal78-card archetype-revealing card gameAgent generate_results
realmMoney RealmrealmVisual / mystical variation of DealAgent generate_results (shares Deal engine)

Where each format is served

                    ┌─────────────────────────────────────────────┐
                    │ Platform host: quiz.thesynergygroup.ch      │
                    │ (Next.js moneyquiz-app pod)                 │
                    │                                             │
                    │  /            → Money Mirror (qa)           │
                    │  /mirror      → re-export of /              │
                    │  /quiz        → tenant-router               │
                    │  /game        → Money Game                  │
                    │  /deal        → Money Deal                  │
                    │  /realm       → Money Realm                 │
                    │  /chooser     → 5-card selection page       │
                    └─────────────────────────────────────────────┘
                              ▲
                              │  iframe with ?tenant=mmc
                              │
                    ┌─────────┴────────────────────────────────────┐
                    │ MMC host: mindfulmoneycoaching.online         │
                    │ (WordPress)                                   │
                    │                                               │
                    │  /money-quiz/   → NATIVE WP page (Likert)     │
                    │  /money-mirror/ → iframe (Mirror)             │
                    │  /money-game/   → iframe (Game)               │
                    │  /money-deal/   → iframe (Deal)               │
                    │  /money-realm/  → iframe (Realm)              │
                    └───────────────────────────────────────────────┘

The four iframe pages are auto-created by mmc-moneyquiz-bridge/auto-pages.php on admin_init (idempotent via option flag). WordPress post IDs 21692–21695.

The /money-quiz/ Likert page is a native WordPress page (not an iframe) — it has its own theme template at page-money-quiz.php and JS engine at traditional-quiz-engine.js. After the user completes the 112 questions, the JS POSTs scores to /wp-json/sg-course/v1/archetype-scores, which then calls the gateway's /calibrate endpoint before writing to mq_* tables. See 09 MMC bridge.


Alias map

The platform accepts both new (canonical) and legacy IDs at every system boundary. Aliases live in api-gateway/registry/assessment.py::FORMAT_ALIASES and Personas/_format_aliases.py.

Legacy idCanonical idWhere it lingered
quizqaPre-rename name for Q&A format
traditionallikertPre-rename name for the 112-Likert format
qa_quizqaPersona dev script naming
mq-conversationqaOlder MMC marketing naming
mq-likertlikertOlder MMC marketing naming
mq-binarylikertA/B variant naming in MMC GA4 events

The normalize_format_id() function in assessment.py is the single normalization point. Every system boundary that reads a format id should call it.


URL composition

Every tenant's per-format URLs are composed by compose_tenant_urls() (Python, gateway) and mirrored in the dashboard preview by composePreview(). See 02 Tenancy model §Per-tenant URLs for the rule.

The composed map appears in /resolved responses as _tenant_urls:

{
  "_tenant_urls": {
    "likert": "https://mindfulmoneycoaching.online/money-quiz/",
    "qa":     "https://mindfulmoneycoaching.online/money-mirror/",
    "game":   "https://mindfulmoneycoaching.online/money-game/",
    "deal":   "https://mindfulmoneycoaching.online/money-deal/",
    "realm":  "https://mindfulmoneycoaching.online/money-realm/"
  }
}

Note: _tenant_urls.likert comes from tenant_brand.canonical_quiz_url (a separate field), NOT from URL composition with the platform default. This is because the Likert path is fully tenant-controlled — every tenant decides where it hosts the WP plugin.


How a quiz session knows which format it is

Three places where the format id matters:

  1. Public quiz route: each format has a dedicated route in moneyquiz-app/src/app/mirror/page.tsx, game/page.tsx, deal/page.tsx, realm/page.tsx. The route itself is the format selector.

  2. Agent session: a session row in Redis stores framework_name + a format field that distinguishes qa from game (both go through quiz_engine). Set when start_quiz (or its alias start_qa) action is invoked.

  3. Webhook payload: the source and response_format fields in the archetype-scores webhook payload distinguish format on the receiver side:

    {"source": "money-mirror", "response_format": "qa"}
    {"source": "money-game",   "response_format": "game"}
    {"source": "the-deal",     "response_format": "deal"}
    

The MMC receiver writes response_format to the mq_taken.Response_Format column so Quiz Leads can filter by format.


Scoring path per format

Each format has a different scoring path, but all five apply the same Tier-2 calibration rules as of 2026-05-19. See 06 Scoring + calibration for the full engine.

FormatPlayer flowScore derivationCalibration applied at
likertWP page with 112 Likert questionsJS sums weighted trait values per archetypeGateway /calibrate (via WP receiver)
qaAdaptive Q&A, ~7 questions, picks from a bank of ~30Agent process_answer updates session scores; final scores POSTed to /api/quiz/resultsTS analyseScores
game6 rounds, ~36 interactions, fastGame session accumulates per-archetype scores during playTS analyseScores
dealCard-game UX, ~60 cardsAgent NATS session; generate_results returns final scores + narrativeAgent generate_results (Python)
realmVisual variation of DealSame as DealSame as Deal

Adding a new format

Order of operations (mirrors the C-phase pattern — alias layer first):

  1. Choose a canonical id (short lowercase, e.g. wheel).
  2. Add to the framework JSON under dimensions (if it has new dimensions) or modes (if it's a new way of asking the same questions).
  3. Add a slug entry to FORMAT_BARE_SLUGS in both framework_config.py and the dashboard preview at brand/page.tsx. Use the same {id, slug, display} shape.
  4. If it has wire-level NATS interactions, register actions in the agent (e.g. start_wheel) and add aliases to FORMAT_ALIASES.
  5. Add the public route at moneyquiz-app/src/app/<slug>/page.tsx. Wire the format-specific UI.
  6. Add a dashboard mode editor at dashboard/src/app/[locale]/assessments/[framework]/modes/<slug>/page.tsx. Pattern after modes/quiz/page.tsx (Money Quiz Likert editor).
  7. Update the MODES array in modes/page.tsx hub.
  8. Add to MMC auto-pages if tenant-hosted iframes are needed: extend MMC_BRIDGE_AUTO_PAGES in auto-pages.php.
  9. Update this section with the new format.

Don't skip the alias layer if you're renaming an existing format. See feedback_alias_first_multi_phase_rename.md for the methodology.


History

DatePhaseChange
2026-05-17(pre-rename)Format names were a mix: Legacy Quiz / Q&A Quiz / The Game / The Realm
2026-05-18 C1AliasesGateway accepts qa, likert, mq-mirror, mq-quiz alongside legacy ids. Idempotent rollout.
2026-05-18 C2Routes + schemaTSG routes added (/chooser, /mirror, /realm, /quiz); MMC auto-pages mu-plugin created (/money-mirror/, /money-game/, /money-deal/, /money-realm/). Migration 0008 adds tenant_brand.slug_prefix.
2026-05-18 C3Personas dev scriptsqa_quizqa in test harness.
2026-05-18 C4Dashboard editor foldersmodes/quiz/ (was QA editor) → modes/mirror/; modes/likert/ (was 112-trait) → modes/quiz/. 308 redirect added.
2026-05-18 C5URL composercompose_tenant_urls() ships _tenant_urls map.
2026-05-18 C6DB mode keysTSG mode_overrides.quiz migrated to .qa, orphan quiz key dropped via direct SQL. Resolver _canonicalize_mode_keys() added.
2026-05-18 C7NATS aliasesstart_qa registered as alias for start_quiz.
2026-05-18 C8In-product copy"Share the Money Quiz" → "Share the Money Mirror" on booked page; GameBoard "The Money Game" → "Money Game".
2026-05-18 C9File/dir cleanupsrc/components/deal/realm/src/components/realm/. Dead app/deal/realm/page.tsx removed.
2026-05-19 DWebhook + calibration parityMirror/Game/Deal now POST to per-tenant CRM via tenant_brand.archetype_scores_webhook. Likert calibrated via gateway /calibrate bridge.

Deferred: MMC theme traditional-quiz-engine.jsmoney-quiz-engine.js rename (touches live WP + 10+ refs).


Anti-patterns to avoid

  • Hardcoding a format id literal anywhere outside of FORMAT_BARE_SLUGS / FORMAT_ALIASES. Always go through normalize_format_id() or canonicalize().
  • Adding format names in i18n keys. Use generic keys like modes.title not modes.qa.title. Change "Money Mirror" by editing the value, not by renaming the key.
  • Forgetting the dashboard route → page.tsx mapping. Every sidebar nav href must have a matching page.tsx. See feedback_nextjs_dashboard_navvsroute.md.
  • Renaming WP / SEO-loaded paths to "match" canonical naming. SEO equity beats cosmetic consistency. Leave existing URLs frozen, document the mismatch.

Next

04 Config schema — the 8 override columns, snapshots, and migrations.