πŸ“‹ Reference

WHITE LABEL ARCHITECTURE

System reference β€” current state

Medhavy adaptive learning platform Β· multi-tenant white label system

Version 1.0 | March 2026 | Reviewed by Dev the Dev
What this document is This is a reference document. It describes the Medhavy white label system as it currently exists β€” stack, configuration schema, analytics payload, pipeline stages, and known gaps. It is not a deployment guide and not a pedagogical explanation. Use it to look things up, not to learn how to deploy or to understand why the architecture is designed as it is. Those are separate documents.

1. Platform stack

Current as of March 2026. Live deployments: Science, Physics. White label slots: available.

LayerTechnologyNotes
Frontend frameworkNext.jsApp router. Per-deployment layout via hostname resolution.
AuthenticationClerk (B2B org pattern)Each institutional client = one Clerk Organization. Learners scoped to org.
Session tokensJWT, 24-hour expiryHub verifies on every page load β€” see gap AI-003.
Search / retrievalOrama (semantic)One isolated index per deployment. No cross-tenant data.
AI pipelineOpenAITwo-stage: analyze-context β†’ chat. See pipeline section.
Analytics storageSupabaseWebhook receiver bypasses 16KB Clerk ceiling. See gap TD-008.
Hub / registryhub.medhavy.comAuthentication Β· registry Β· analytics Β· access control Β· dashboard.
Content formatMDX via FumadocsIndexed into Orama at publish time.
StylingTailwind + CSS variablesTheme injected at root layout via next-themes. Per-tenant config object.

2. System architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     MEDHAVI HUB (hub.medhavy.com)                    β”‚
β”‚  Authentication Β· Registry Β· Analytics Β· Access Control Β· Dashboard  β”‚
β”‚  Stack: Next.js Β· Clerk Β· JWT (24hr sessions)                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β–Ό             β–Ό              β–Ό
   [deployment-A]  [deployment-B]  [deployment-N]
   (Live: Science)  (Live: Physics)  (White Label Slot)
          β”‚              β”‚              β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚         AI CHAT PIPELINE (Per Deployment)    β”‚
          β”‚  Stage 1: /api/analyze-context               β”‚
          β”‚    β†’ question + page context + history       β”‚
          β”‚    β†’ keywords + tags + follow-ups + plan     β”‚
          β”‚    β†’ active pedagogy mode injected here      β”‚
          β”‚  Stage 2: /api/chat                          β”‚
          β”‚    β†’ Orama semantic search (isolated index)  β”‚
          β”‚    β†’ Sources + pedagogy prompt injected      β”‚
          β”‚    β†’ SSE stream: sources β†’ tokens β†’ done     β”‚
          β”‚  Rule: Not in textbook β†’ "Not in textbook."  β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚    BANDIT LAYER (Pedagogical selection)      β”‚
          β”‚  Tracks: approach β†’ outcome β†’ update         β”‚
          β”‚  Selects from: Direct Β· Socratic Β· Case Β·   β”‚
          β”‚    Retrieval Β· Project                       β”‚
          β”‚  Updates: per learner, per session, per topicβ”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚    PERSONA LAYER (Swappable per client)      β”‚
          β”‚  Tone Β· Depth Β· Examples Β· Disclaimer        β”‚
          β”‚  Stored in tenant registry β€” not in code     β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. Tenant registry schema

⚠ Gap TD-001 β€” not yet implemented The tenant registry currently lives in Clerk organization metadata, which has a 16KB ceiling and no structured lookup. The schema below represents the target state. The minimum viable implementation is tenants.json or an Edge Config KV store. See the gap matrix in section 6.

Each key is the institutional deployment hostname. All fields are required unless marked optional.

{
  "[client].medhavy.com": {
    "orgId":           "org_clienta_2026",      // Clerk organization ID
    "textbooks":       ["ai-literacy-v1"],       // array of textbook identifiers
    "oramaIndex":      "[ENV: ORAMA_INDEX_X]",   // env var name β€” not the key value
    "oramaKey":        "[ENV: ORAMA_KEY_X]",     // env var name β€” not the key value
    "persona":         "corporate-advisor",      // persona identifier β€” see section 4
    "pedagogy": {
      "active":        ["case-based", "project-based"],  // approaches bandit tests
      "bandwidthTest": false,                            // true = test all five
      "default":       "direct-instruction"             // fallback if bandit uninit
    },
    "badgeIssuer":     "[Institution Name]",     // appears on credential
    "textbookOnly":    true                      // AI restricted to textbook content
  }
}

Field reference

FieldTypeRequiredNotes
orgId string Required Clerk organization ID. All API routes filter by this value.
textbooks string[] Required Array of textbook identifiers. Must match Orama index content.
oramaIndex string Required Name of the environment variable holding the Orama index ID β€” not the ID itself. See gap TD-003.
oramaKey string Required Name of the environment variable holding the Orama API key β€” not the key itself. See gap TD-003.
persona string Required Persona identifier. Must match an entry in the persona config store. See section 4.
pedagogy.active string[] Required Valid values: direct-instruction Β· socratic Β· case-based Β· spaced-retrieval Β· project-based
pedagogy.bandwidthTest boolean Optional If true, bandit tests all five approaches regardless of active array. Default: false.
pedagogy.default string Required Fallback approach used before the bandit has enough data to select. Must be in active array.
badgeIssuer string Required Institution name as it appears on issued credentials.
textbookOnly boolean Required If true, AI responds "Not in textbook." to any question outside indexed content. Always true for white label deployments.

4. Theme configuration schema

Theme config is injected at root layout via next-themes and Tailwind CSS variables. No code changes required per deployment β€” all values are data.

const clientTheme = {
  institutionName:  "[Institution Full Name]",
  platformName:     "[Institution] AI Learning Lab",
  primaryColor:     "[Brand hex β€” 6-digit]",
  secondaryColor:   "[Brand hex β€” 6-digit]",
  logoUrl:          "/logos/[client]-logo.png",
  faviconUrl:       "/favicons/[client]-favicon.ico",
  fontFamily:       "'Inter', sans-serif",
  domain:           "[client].medhavy.com",

  persona: {
    name:           "[Institution] AI Advisor",
    tone:           "authoritative | empathetic | inquisitive | structured",
    depth:          "decision-support | conceptual | foundational | applied",
    examples:       "finance | policy | curriculum | clinical | general",
    disclaimer:     "Responses sourced from [Institution]-verified materials only.",
    textbookOnly:   true
  }
};

Valid persona tone values

ValueBehaviorTypical deployment
authoritativeDirect, concise, decision-oriented. Minimal hedging.Executive education, professional associations
empatheticEncouraging, patient, checks understanding frequently.K-12 networks
inquisitiveResponds to answers with questions. Resists giving direct answers.Think tanks, policy organizations
structuredFramework-forward. Names the model before applying it.Curriculum organizations

Valid persona depth values

ValueBehavior
decision-supportOrients responses toward actionable decisions. ROI-framing.
conceptualPrioritizes understanding over application. Policy and research contexts.
foundationalAssumes minimal prior knowledge. Defines before using.
appliedTies every concept to a concrete task or output.

5. Analytics payload schema

⚠ Gap TD-008 β€” Supabase sync not yet live The payload below is the target schema for the Supabase webhook receiver at POST /api/analytics/ingest. This endpoint does not yet exist. See gap matrix.
POST /api/analytics/ingest
{
  "orgId":        "org_clienta_2026",          // required β€” Clerk org
  "userId":       "[anonymized-hash]",          // required β€” never raw PII
  "event":        "ai_interaction",             // event type
  "pedagogy":     "case-based",                // active approach at time of event
  "chapter":      "module-3-application",      // textbook chapter identifier
  "query":        "[learner question text]",   // stored for grounding audit only
  "response":     "grounded",                  // enum: grounded | not_in_textbook
  "mouseTrace":   {
    "path":       [...],                        // coordinate array
    "dwellMs":    4200                          // milliseconds on section
  },
  "bandyUpdate":  {
    "approach":   "case-based",
    "outcome":    "positive"                    // enum: positive | neutral | negative
  },
  "timestamp":    "2026-04-01T14:23:00Z"
}

Event type reference

event valueDescriptionRequired fields
ai_interactionLearner submitted a query to the AI tutorall
chapter_openLearner opened a textbook chapterorgId, userId, chapter, timestamp
chapter_completeLearner marked chapter complete or scrolled to endorgId, userId, chapter, timestamp
session_startNew authenticated session beganorgId, userId, timestamp

bandyUpdate.outcome values

ValueCondition
positiveLearner continued engagement after response β€” follow-up question, chapter progression
neutralSession ended without clear positive or negative signal
negativeLearner disengaged, repeated same question, or explicitly indicated confusion

6. Technical gap priority matrix

CRITICAL and HIGH gaps must be resolved before any external institutional deployment. BACKLOG items are not blockers at pilot scale.

IDDescriptionPriorityMinimum viable fixSprint
TD-001 Tenant registry lives in Clerk org metadata. No structured lookup. Blocks multi-tenant routing. CRITICAL Implement tenants.json or Edge Config KV. Map hostname β†’ Orama credentials + persona + pedagogy + content manifest. Sprint 1
TD-003 Orama credentials hard-coded in source. Security and multi-tenant blocker. CRITICAL Migrate all Orama keys to environment variables, one env var pair per tenant. Registry references env var names, not values. Sprint 1
TD-008 All analytics stored in Clerk org metadata. 16KB ceiling hit at moderate interaction volume. HIGH Supabase webhook receiver at /api/analytics/ingest. See payload schema in section 5. Sprint 1
Theme config Branding changes require code edits. Every new client needs a developer. HIGH CSS variable injection at root layout from tenant config object. See theme schema in section 4. Sprint 1
Pedagogy selector Bandit approach selection not wired to Stage 1 system prompt. Pedagogy config exists in registry but has no effect on AI behavior. HIGH Inject active pedagogy mode from tenant config into Stage 1 context analysis prompt. Five prompt variants required β€” one per approach. Sprint 1
TD-005 TEXTBOOK_ONLY not enforced in Science deployment. New deployments should use Template/Physics logic. NOT A BLOCKER New white label deployments built on Template/Physics branch. Science deployment isolated from white label rollout. Backlog
AI-003 Hub verifies JWT on every page load. Performance cost at scale. LOW Session caching. Defer until after first pilot β€” not a correctness issue, a performance issue. Sprint 2
TD-009 User iteration not synced on delete events. Stale data risk. LOW Defer. Not triggered at pilot scale. Sprint 3

7. Supported deployment types

This table defines expected configuration defaults by institution type. All values are overridable per tenant.

Institution type Default pedagogy.active Default persona.tone Default persona.depth
Business school executive education case-based, project-based authoritative decision-support
Think tank / policy organization socratic, case-based inquisitive conceptual
Curriculum organization direct-instruction, project-based structured applied
Private K-12 network spaced-retrieval, project-based empathetic foundational
Professional association direct-instruction, spaced-retrieval authoritative foundational