quarkshologridledger/reference/FRONTEND.md

48 KiB
Raw Blame History

Frontend Architecture: Quark's Holo-Grid Ledger

Status: Design Analysis — Pre-Implementation
Dependencies: reference/ENGINE.md, data-source/taxonomy.yaml, AGENTS.md
Framework: TanStack Start + TanStack Router (file-based routing)


1. Layout Topology

The application uses a fixed-viewport, three-column terminal layout defined in __root.tsx. The root shell is persistent — only the center column swaps content via <Outlet />.

┌────────────────────────────────────────────────────────────────────────────┐
│ [=] QUARK'S HOLO-GRID LEDGER // SUB-NET RECEPTOR     STARDATE: 54201.3   │
│                                                    BALANCE: 4,250.00 GPL  │
├──────────────┬────────────────────────────────┬────────────────────────────┤
│              │                                │                            │
│  LEFT PANEL  │       CENTER PANEL             │       RIGHT PANEL          │
│  col-span-3  │       col-span-6               │       col-span-3           │
│              │                                │                            │
│  Navigation  │       <Outlet />               │       Betslip              │
│  Sidebar     │       (route content)          │       Sidecar              │
│              │                                │                            │
│  240px-ish   │       flex-1                   │       280px-ish            │
│              │                                │                            │
├──────────────┴────────────────────────────────┴────────────────────────────┤
│ SYSTEM RUNTIME: OK // CORE MODULES ACTIVE               TANSTACK + VITE  │
└────────────────────────────────────────────────────────────────────────────┘

Responsive Breakpoints

DESKTOP (≥1280px):  [col-3 Sidebar] [col-6 Main] [col-3 Betslip]
TABLET  (768-1279): [col-2 Sidebar] [col-7 Main] [col-3 Betslip]  (sidebar compressed)
MOBILE  (<768):     [Full-width Main] + bottom tab bar + slide-up betslip

On mobile, the sidebar collapses into a bottom navigation bar with 5 terminal command buttons, and the betslip becomes a pull-up sheet triggered from the bar.

┌────────────────────────────────────────┐
│  QUARK'S HOLO-GRID LEDGER   4,250 GPL │
├────────────────────────────────────────┤
│                                        │
│         MAIN CONTENT                   │
│         (full-width)                   │
│                                        │
│                                        │
├────────────────────────────────────────┤
│  GRID  │ ALPHA │ BETA │ SLIP │ LEDGER │
│   ◈    │   α   │  β   │  ₲   │   ▤    │
└────────────────────────────────────────┘

2. Navigation Sidebar (Left Panel)

The sidebar is the primary navigation interface. It must feel like a hardware command console — numbered entries, hierarchical quadrant trees, and live status indicators.

2.1 Sidebar Sections

╔══════════════════════════════════╗
║ [ SYSTEM ARRAY ] Quadrants      ║
╠══════════════════════════════════╣
║                                  ║
║  > GRID OVERVIEW            [00] ║  ← Link to /
║                                  ║
║  ═══════════════════════════════ ║
║  > LIVE ENGAGEMENTS              ║  ← Section header
║                                  ║
║  ▾ ALPHA QUADRANT           [α]  ║  ← Collapsible quadrant group
║    ├─ ◆SFC vs █BRG   ●LIVE      ║  ← Active match (link to /quadrants/{id})
║    │   62% ████░░ 71%            ║  ← Inline shield bars
║    ├─ ▼CRD vs ☼BAJ   ●LIVE      ║
║    │   48% ███░░░ 55%            ║
║    └─ ⚔KLG vs ◈ROM   ○PRE      ║  ← Pre-match (different indicator)
║                                  ║
║  ▸ BETA QUADRANT            [β]  ║  ← Collapsed quadrant
║    2 active                      ║
║                                  ║
║  ▸ GAMMA QUADRANT           [γ]  ║
║    1 active                      ║
║                                  ║
║  ▸ DELTA QUADRANT           [δ]  ║
║    3 active                      ║
║                                  ║
║  ═══════════════════════════════ ║
║  > STATION ARCHIVES              ║  ← Section header
║                                  ║
║  [01] Wager Ledger               ║  ← Link to /ledger
║  [02] Faction Registry           ║  ← Link to /registry/factions
║  [03] Venue Database             ║  ← Link to /registry/venues
║  [04] Transmission Schedule      ║  ← Link to /schedule
║                                  ║
╚══════════════════════════════════╝

2.2 Live Match Items

Each match in the sidebar should show at a glance:

  • Faction glyphs and abbreviations (e.g., ◆SFC vs █BRG)
  • Match status indicator: ●LIVE (pulsing green) / ○PRE (amber) / ◉RES (red)
  • Compact shield capacity bars (optional, space permitting)
  • Clicking navigates to /quadrants/{sectorId}?quadrant=Alpha&currency=Latinum

2.3 Sidebar Data Source

The sidebar reads from the sector:index:active Valkey set via a server function that returns all active match summaries. It polls at the same 2s interval as match telemetry.

// Server function: returns lightweight match summaries for sidebar
const getActiveMatchIndex = createServerFn({ method: 'GET' })
  .handler(async () => {
    const matchIds = await valkey.smembers('sector:index:active')
    // For each match, read just the fields needed for sidebar rendering
    // (id, name, quadrant, status, factions.home.abbreviation, factions.away.abbreviation, 
    //  factions.home.shieldCapacity, factions.away.shieldCapacity)
    return summaries
  })

3. Route Map

3.1 File-Based Route Structure

src/routes/
├── __root.tsx                         # Shell layout (header, sidebar, betslip, footer)
├── index.tsx                          # Grid Overview / Dashboard
├── quadrants/
│   ├── index.tsx                      # Quadrant listing (all matches, filterable)
│   └── $sectorId.tsx                  # Live match detail (the main event page)
├── ledger/
│   ├── index.tsx                      # Wager Ledger overview (active + recent settled)
│   ├── active.tsx                     # Active/open wagers only
│   └── settled.tsx                    # Settled/graded wagers history
├── registry/
│   ├── factions.tsx                   # Faction directory (all teams)
│   ├── factions.$factionId.tsx        # Faction detail (stats, form, history)
│   ├── venues.tsx                     # Venue directory (all sectors)
│   └── venues.$venueId.tsx            # Venue detail (modifiers, match history)
└── schedule.tsx                       # Upcoming match schedule

3.2 Route Definitions with Validated Search Params

Every route enforces typed search params via Zod validators per AGENTS.md Rule A.

// ─── / (Grid Overview Dashboard) ───
export const Route = createFileRoute('/')({
  validateSearch: z.object({
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']).optional(),
    currency: z.enum(['Latinum', 'Credits']).default('Latinum'),
  }),
})

// ─── /quadrants (Quadrant Match Listing) ───
export const Route = createFileRoute('/quadrants/')({
  validateSearch: z.object({
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']).optional(),
    status: z.enum(['LIVE', 'PRE_MATCH', 'RESOLVING', 'all']).default('all'),
    currency: z.enum(['Latinum', 'Credits']).default('Latinum'),
    sort: z.enum(['shields', 'yield', 'newest', 'ending']).default('newest'),
  }),
})

// ─── /quadrants/$sectorId (Live Match Detail) ───
export const Route = createFileRoute('/quadrants/$sectorId')({
  validateSearch: z.object({
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']),
    currency: z.enum(['Latinum', 'Credits']).default('Latinum'),
    marketCategory: z.enum(['primary', 'secondary', 'exotic', 'all']).default('all'),
  }),
})

// ─── /ledger (Wager Ledger) ───
export const Route = createFileRoute('/ledger/')({
  validateSearch: z.object({
    status: z.enum(['active', 'settled', 'all']).default('all'),
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']).optional(),
    currency: z.enum(['Latinum', 'Credits']).default('Latinum'),
    page: z.number().default(1),
  }),
})

// ─── /registry/factions (Faction Directory) ───
export const Route = createFileRoute('/registry/factions')({
  validateSearch: z.object({
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']).optional(),
    type: z.enum(['aggressive', 'defensive', 'tactical', 'infiltrator', 'swarm']).optional(),
    sort: z.enum(['name', 'attack', 'shield', 'evasion', 'winrate']).default('name'),
  }),
})

// ─── /registry/venues (Venue Directory) ───
export const Route = createFileRoute('/registry/venues')({
  validateSearch: z.object({
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']).optional(),
    sort: z.enum(['name', 'shield_mod', 'damage_mod', 'chaos']).default('name'),
  }),
})

// ─── /schedule (Upcoming Matches) ───
export const Route = createFileRoute('/schedule')({
  validateSearch: z.object({
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']).optional(),
    currency: z.enum(['Latinum', 'Credits']).default('Latinum'),
  }),
})

4. Page Designs

4.1 Grid Overview Dashboard (/)

The landing page — a high-density terminal dashboard showing all active engagements at a glance.

┌──────────────────────────────────────────────────────────────────┐
│ [ CONSOLE TERMINAL ] Active Feeds                                │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  > SUBSPACE BROADCAST — LIVE ENGAGEMENTS ACROSS ALL QUADRANTS    │
│  ════════════════════════════════════════════════════════════     │
│                                                                  │
│  ┌─── FILTER ─────────────────────────────────────────────────┐  │
│  │ [ALL]  [α ALPHA]  [β BETA]  [γ GAMMA]  [δ DELTA]          │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐     │
│  │  SECTOR 001 — EARTH ORBITAL ARRAY          ●LIVE  α     │     │
│  │  ◆ Starfleet Command    62%  ████████░░░   VS           │     │
│  │  █ Borg Collective      71%  █████████░░              │     │
│  │  ──────────────────────────────────────────────────     │     │
│  │  KY: 14.7 TW    TICK: 42/90    ODDS: SFC 2.85 | BRG 1.48   │
│  │  ▸ 6 MARKETS OPEN                          [VIEW] →    │     │
│  └─────────────────────────────────────────────────────────┘     │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐     │
│  │  THE BADLANDS — PLASMA STORM ZONE          ●LIVE  α     │     │
│  │  ▼ Cardassian Union     48%  ██████░░░░    VS           │     │
│  │  ☼ Bajoran Militia      55%  ███████░░░              │     │
│  │  ──────────────────────────────────────────────────     │     │
│  │  KY: 8.2 TW     TICK: 31/75    ODDS: CRD 2.10 | BAJ 1.72   │
│  │  ▸ 8 MARKETS OPEN                          [VIEW] →    │     │
│  └─────────────────────────────────────────────────────────┘     │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐     │
│  │  NARENDRA III — HONOR'S EDGE               ○PRE   β     │     │
│  │  ⚔ Klingon Empire                          VS           │     │
│  │  ◈ Romulan Star Empire                                │     │
│  │  ──────────────────────────────────────────────────     │     │
│  │  COMMENCING IN: 00:47        PRE-MATCH ODDS AVAILABLE   │     │
│  │  ▸ 4 MARKETS OPEN                          [VIEW] →    │     │
│  └─────────────────────────────────────────────────────────┘     │
│                                                                  │
│  ┌─ LIVE TICKER ──────────────────────────────────────────┐     │
│  │ 14:32 Borg Adaptation triggered — Damage reduced 50%   │     │
│  │ 14:30 Critical Hit! Starfleet deals 3× damage          │     │
│  │ 14:28 Bajor: Prophet Intervention — Markets SUSPENDED   │     │
│  │ 14:25 New match: Klingons vs Romulans @ Narendra III    │     │
│  └────────────────────────────────────────────────────────┘     │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

Key features:

  • Match summary cards with inline shield bars and headline odds
  • Quadrant filter tabs (search param ?quadrant=alpha)
  • Live event ticker scrolling recent events from ALL active matches
  • Pre-match cards show countdown timer instead of combat data
  • Each card links to /quadrants/$sectorId

4.2 Match Detail Page (/quadrants/$sectorId)

The most important page — full live match view with all markets.

┌──────────────────────────────────────────────────────────────────┐
│ [ ENGAGEMENT MATRIX ] Wolf 359 — Memorial Perimeter              │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─ VERSUS ARENA ────────────────────────────────────────────┐  │
│  │                                                            │  │
│  │         ◆ STARFLEET COMMAND        █ BORG COLLECTIVE      │  │
│  │              [SFC]                      [BRG]              │  │
│  │                                                            │  │
│  │   SHIELDS   62% ████████░░░   71% █████████░░   SHIELDS   │  │
│  │   ATTACK    58                 99               ATTACK    │  │
│  │   EVASION   40                 12               EVASION   │  │
│  │                                                            │  │
│  │        ─────────── ✦ VS ✦ ──────────                      │  │
│  │                                                            │  │
│  │   KINETIC YIELD: 14.7 TW        TICK: 42 / 90            │  │
│  │   VENUE: Wolf 359 [debris-field, high-anomaly]            │  │
│  │   SHIELD MOD: 0.95  DMG MOD: 1.10  EVA MOD: 0.80         │  │
│  │                                                            │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌─ ACTIVE EFFECTS ──────────────────────────────────────────┐  │
│  │  ⚡ BORG ADAPTATION (BRG) — Incoming damage ×0.5  [3/5]   │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌─ FILTER ───────────────────────────────────────────────────┐ │
│  │ [ALL]  [PRIMARY]  [SECONDARY]  [EXOTIC]                    │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  ┌─ MARKETS ─────────────────────────────────────────────────┐  │
│  │                                                            │  │
│  │  COMBAT RESOLUTION — MONEYLINE                [primary]    │  │
│  │  ┌──────────────────────────┬───────────────────────────┐  │  │
│  │  │ ◆ Starfleet Victory     │ █ Borg Assimilation       │  │  │
│  │  │         [2.85] ▲        │         [1.48] ▼          │  │  │
│  │  └──────────────────────────┴───────────────────────────┘  │  │
│  │                                                            │  │
│  │  FIRST SHIELD BREACH                          [primary]    │  │
│  │  ┌──────────────────────────┬───────────────────────────┐  │  │
│  │  │ ◆ SFC Shields First     │ █ BRG Shields First       │  │  │
│  │  │         [1.65] ▼        │         [2.20] ▲          │  │  │
│  │  └──────────────────────────┴───────────────────────────┘  │  │
│  │                                                            │  │
│  │  TOTAL KINETIC YIELD                          [primary]    │  │
│  │  ┌──────────────────────────┬───────────────────────────┐  │  │
│  │  │ Over 8.5 TW             │ Under 8.5 TW              │  │  │
│  │  │         [1.35] ▼        │         [3.10] ▲          │  │  │
│  │  └──────────────────────────┴───────────────────────────┘  │  │
│  │                                                            │  │
│  │  COMEBACK VICTORY                             [exotic]     │  │
│  │  ┌──────────────────────────┬───────────────────────────┐  │  │
│  │  │ ◆ SFC 30+ Comeback      │ █ BRG 30+ Comeback        │  │  │
│  │  │         [5.50]           │         [8.20] ▲          │  │  │
│  │  └──────────────────────────┴───────────────────────────┘  │  │
│  │                                                            │  │
│  │  MUTUAL DESTRUCTION                           [exotic]     │  │
│  │  ┌──────────────────────────┬───────────────────────────┐  │  │
│  │  │ Both Shields 0%         │ Survivor                   │  │  │
│  │  │        [12.00]           │         [1.05]             │  │  │
│  │  └──────────────────────────┴───────────────────────────┘  │  │
│  │                                                            │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌─ ENGAGEMENT LOG ──────────────────────────────────────────┐  │
│  │  [T42] ◆ Starfleet fires — HIT — 4.2% shield damage      │  │
│  │  [T42] █ Borg fires — MISS — Evasion successful           │  │
│  │  [T38] ⚡ EVENT: Borg Adaptation — Incoming dmg ×0.5      │  │
│  │  [T35] ◆ Starfleet fires — CRIT — 12.6% shield damage    │  │
│  │  [T31] 🌀 EVENT: Debris Impact — BRG shields -12%         │  │
│  │  [T28] █ Borg fires — HIT — 6.1% shield damage           │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

Key features:

  • Versus arena header with full faction stats, shield bars, and active effects
  • Venue modifier display (so bettors understand the environment)
  • Market category filter tabs (search param ?marketCategory=primary)
  • Each market selection is a clickable button that adds to betslip
  • Price trend indicators (▲ up / ▼ down) with color coding
  • Engagement log showing tick-by-tick combat events
  • Market suspension overlay when SUBSPACE INTERRUPTION event fires

4.3 Betslip Sidecar (Right Panel — always visible)

The betslip is NOT a route — it's a persistent panel in the root layout, managed via React context or a lightweight client store.

╔══════════════════════════════════╗
║ [ WAGER SLIP ] Secure Link       ║
╠══════════════════════════════════╣
║                                  ║
║  SELECTIONS (2)                  ║
║  ════════════════════════════    ║
║                                  ║
║  ┌────────────────────────────┐  ║
║  │ Wolf 359 — SFC vs BRG     │  ║
║  │ ◆ Starfleet Victory       │  ║
║  │              [2.85]   [×] │  ║
║  │ STAKE: [___25.00___] GPL  │  ║
║  │ RETURN: 71.25 GPL         │  ║
║  └────────────────────────────┘  ║
║                                  ║
║  ┌────────────────────────────┐  ║
║  │ Badlands — CRD vs BAJ     │  ║
║  │ Over 8.5 Terawatts        │  ║
║  │              [1.85]   [×] │  ║
║  │ STAKE: [___10.00___] GPL  │  ║
║  │ RETURN: 18.50 GPL         │  ║
║  └────────────────────────────┘  ║
║                                  ║
║  ═══════════════════════════════ ║
║  SINGLES TOTAL STAKE:  35.00    ║
║  POTENTIAL RETURN:     89.75    ║
║                                  ║
║  ─── ACCUMULATOR ────────────── ║
║  COMBINED ODDS: [5.27]          ║
║  ACCA STAKE: [________] GPL     ║
║  ACCA RETURN: 0.00 GPL          ║
║                                  ║
║  ═══════════════════════════════ ║
║                                  ║
║  ┌────────────────────────────┐  ║
║  │    ▶ TRANSMIT WAGER ◀     │  ║
║  │  Rule of Acquisition #62  │  ║
║  └────────────────────────────┘  ║
║                                  ║
║  ─── RECENT TRANSMISSIONS ───── ║
║  ✓ SFC Victory @ 2.40  +36.00  ║
║  ✗ Over 8.5 TW @ 1.85  -10.00  ║
║  ○ BRG Victory @ 1.48  PENDING  ║
║                                  ║
╚══════════════════════════════════╝

Key features:

  • Selections added by clicking market buttons on any match page
  • Individual stake inputs per selection (singles)
  • Accumulator option with combined odds
  • Live price updates — if odds change while in betslip, show old→new with flash
  • Odds lock warning if price moves significantly
  • Recent bet results at the bottom
  • Persistent across route changes (React context, not URL state)

4.4 Wager Ledger (/ledger)

┌──────────────────────────────────────────────────────────────────┐
│ [ WAGER LEDGER ] Transaction Archive                             │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─ FILTER ───────────────────────────────────────────────────┐ │
│  │ [ALL]  [ACTIVE]  [SETTLED]    Quadrant: [ALL ▾]            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  ┌─ ACCOUNT SUMMARY ─────────────────────────────────────────┐  │
│  │  BALANCE: 4,250.00 GPL   ACTIVE RISK: 285.00 GPL          │  │
│  │  SESSION P/L: +127.50 GPL  ▲                               │  │
│  │  WIN RATE: 58% (14/24)    AVG ODDS: 2.15                  │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ─── ACTIVE WAGERS ──────────────────────────────────────────── │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │  #W-0042  Wolf 359 — SFC vs BRG              ●LIVE  α     │  │
│  │  Selection: ◆ Starfleet Victory                            │  │
│  │  Odds Taken: 2.85    Stake: 25.00 GPL                      │  │
│  │  Current Odds: 3.10  Potential: 71.25 GPL                  │  │
│  │  Status: OPEN — Shields: SFC 62% | BRG 71%                │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ─── SETTLED WAGERS ─────────────────────────────────────────── │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │  #W-0039  Qo'noS Arena — KLG vs GRN        ✓ WON    β    │  │
│  │  Selection: ⚔ Klingon Victory                              │  │
│  │  Odds: 1.65    Stake: 30.00    Return: 49.50 GPL  +19.50  │  │
│  └────────────────────────────────────────────────────────────┘  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │  #W-0037  Badlands — CRD vs BAJ             ✗ LOST   α    │  │
│  │  Selection: Over 8.5 TW                                    │  │
│  │  Odds: 1.85    Stake: 10.00    Return: 0.00 GPL   -10.00  │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

4.5 Faction Registry (/registry/factions)

┌──────────────────────────────────────────────────────────────────┐
│ [ FACTION REGISTRY ] Combatant Database                          │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─ FILTER ───────────────────────────────────────────────────┐ │
│  │ Quadrant: [ALL ▾]    Type: [ALL ▾]    Sort: [NAME ▾]       │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  GLYPH  FACTION              QDR  TYPE         SHD  ATK  EVA   │
│  ═════  ═══════════════════  ═══  ═══════════  ═══  ═══  ═══   │
│  ◆      Starfleet Command     α   defensive     92   65   50   │
│  █      Borg Collective       δ   swarm          95   90   15   │
│  ⚔      Klingon Empire        β   aggressive     60   95   35   │
│  ◈      Romulan Star Empire   β   infiltrator    72   70   85   │
│  ◉      The Dominion          γ   swarm          75   88   40   │
│  ∞      Species 8472          δ   aggressive     99   99   70   │
│  ...                                                             │
│                                                                  │
│  Click a faction row to view detailed profile →                  │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

Clicking a faction row navigates to /registry/factions/$factionId, which shows:

  • Full tactical profile text
  • Rivalry modifiers table
  • Active matches this faction is in
  • Recent match history (W/L record)
  • Type advantage breakdown

4.6 Venue Database (/registry/venues)

┌──────────────────────────────────────────────────────────────────┐
│ [ VENUE DATABASE ] Sector Pool Registry                          │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  VENUE                    QDR   SHD×   DMG×   EVA×   ANOMALY   │
│  ═══════════════════════  ════  ═════  ═════  ═════  ════════   │
│  Fluidic Space Rift        δ    0.60   1.50   0.80   35%  !!!  │
│  The Badlands              α    0.70   1.30   0.60   35%  !!!  │
│  Founders' Approach        γ    0.85   1.10   0.60   40%  !!!  │
│  Qo'noS Arena              β    0.80   1.25   0.95    8%       │
│  Vulcan Defense Grid        α    1.20   0.85   1.00    3%       │
│  Nekrit Expanse             δ    1.00   1.00   1.00    1%       │
│  ...                                                             │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

4.7 Match Schedule (/schedule)

┌──────────────────────────────────────────────────────────────────┐
│ [ TRANSMISSION SCHEDULE ] Upcoming Engagements                   │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ─── SCHEDULED (starting soon) ────────────────────────────────  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │  T-47s   Narendra III — Honor's Edge              [β]      │  │
│  │          ⚔ Klingon Empire  vs  ◈ Romulan Star Empire       │  │
│  │          Rivalry: 1.30 — MARQUEE MATCHUP                   │  │
│  │          Pre-match odds available at T-60s                  │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │  T-2m    Gornar Orbit — Hegemony Arena            [β]      │  │
│  │          ▲ Gorn Hegemony  vs  ⊘ Orion Syndicate            │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ─── RECENTLY SETTLED ─────────────────────────────────────────  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │  SETTLED  Vulcan Grid — T'Khasi Defense Grid      [α]      │  │
│  │           ◆ Starfleet Command  68%  vs  ₲ Ferengi  0%     │  │
│  │           RESULT: Starfleet Victory — 72 ticks              │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

5. Component Architecture

Per AGENTS.md, route files contain only configuration. All visual markup lives in components.

5.1 Component Map

src/components/
├── ascii/                          # Low-level visual primitives
│   ├── AsciiPanel.tsx              # Bordered panel container (EXISTS)
│   ├── ShieldBar.tsx               # Horizontal shield capacity bar
│   ├── PriceTag.tsx                # Odds display with trend indicator
│   ├── StatusBadge.tsx             # LIVE/PRE/RESOLVING/SETTLED indicator
│   ├── TerminalLine.tsx            # Decorative separator line
│   ├── BlinkingCursor.tsx          # Animated cursor for loading states
│   ├── TickProgress.tsx            # Match progress bar (tick X / maxTicks)
│   └── GlyphIcon.tsx              # Faction glyph renderer with color
│
├── panels/                         # Domain feature views (large composites)
│   ├── NavigationMenu.tsx          # Left sidebar navigation (EXISTS)
│   ├── BetslipSidecar.tsx          # Right sidebar betslip
│   ├── MatchCard.tsx               # Summary card for dashboard grid
│   ├── VersusArena.tsx             # Full faction-vs-faction header
│   ├── MarketGrid.tsx              # All markets for a match
│   ├── MarketSelection.tsx         # Single clickable odds button
│   ├── EngagementLog.tsx           # Scrolling event log for a match
│   ├── LiveTicker.tsx              # Global event feed (dashboard)
│   ├── FactionTable.tsx            # Sortable faction directory table
│   ├── VenueTable.tsx              # Sortable venue directory table
│   ├── FactionProfile.tsx          # Detailed faction stats view
│   ├── WagerCard.tsx               # Single bet display (active or settled)
│   ├── AccountSummary.tsx          # Balance, P/L, win rate stats
│   ├── ScheduleCard.tsx            # Upcoming/settled match card
│   └── QuadrantFilterBar.tsx       # Reusable quadrant filter tabs
│
└── providers/                      # Client state providers
    ├── BetslipProvider.tsx          # Betslip selection state (React Context)
    └── CurrencyProvider.tsx        # Active currency preference

5.2 Route → Component Mapping

Routes stay thin (AGENTS.md compliance). Heavy rendering delegates to panel components.

// src/routes/quadrants/$sectorId.tsx — THIN ROUTE FILE
export const Route = createFileRoute('/quadrants/$sectorId')({
  validateSearch: z.object({
    quadrant: z.enum(['alpha', 'beta', 'gamma', 'delta']),
    currency: z.enum(['Latinum', 'Credits']).default('Latinum'),
    marketCategory: z.enum(['primary', 'secondary', 'exotic', 'all']).default('all'),
  }),
  loader: async ({ params }) => {
    const snapshot = await getCachedSectorData({ input: params.sectorId })
    return { snapshot }
  },
  component: MatchDetailView,  // ← delegates to panel
})

// The actual MatchDetailView component lives in src/components/panels/
// It composes: VersusArena + MarketGrid + EngagementLog

6. Data Flow & Server Functions

6.1 Server Function Registry

src/server/
├── db/
│   └── valkeyConnector.ts          # Valkey client instance
└── functions/
    ├── getActiveMatchIndex.ts      # All active match summaries (sidebar)
    ├── getMatchTelemetry.ts        # Full match state for detail page
    ├── getUpcomingSchedule.ts      # Scheduled matches
    ├── getSettledMatches.ts        # Recently settled results
    ├── getFactionRegistry.ts       # Static faction data from taxonomy
    ├── getVenueRegistry.ts         # Static venue data from taxonomy
    └── submitWager.ts              # Place a bet (write to Valkey)

6.2 Polling Strategy

Data Interval Source Route
Active match index (sidebar) 2s sector:index:active __root.tsx (always)
Match telemetry (detail page) 2s sector:telemetry:{id} /quadrants/$sectorId
Match events (detail page) 2s sector:events:{id} /quadrants/$sectorId
Dashboard match cards 2s All active telemetry /
Schedule 10s sector:schedule:upcoming /schedule
Faction/venue registry Static taxonomy.yaml (cached) /registry/*
Betslip price updates 2s Individual market keys BetslipSidecar

6.3 SSR + Client Hydration Pattern

// Pattern for all live data routes:

// 1. Loader runs on server — fetches initial snapshot from Valkey
loader: async ({ params }) => {
  return await getCachedSectorData({ input: params.sectorId })
},

// 2. Component hydrates with loader data, then starts client polling
function MatchDetailView() {
  const initialData = Route.useLoaderData()
  
  const { data } = useQuery({
    queryKey: ['telemetry', sectorId],
    queryFn: () => getCachedSectorData({ input: sectorId }),
    initialData,           // SSR data used immediately
    refetchInterval: 2000, // Client polls every 2s after hydration
  })
}

7. Client State Management

Only two pieces of state live on the client (not URL, not server):

7.1 Betslip State (React Context)

interface BetslipSelection {
  matchId: string
  matchName: string
  marketId: string
  selectionName: string
  price: number          // Price when added
  currentPrice: number   // Live price (updated by polling)
  stake: number          // User-entered stake
  factionGlyph: string
}

interface BetslipState {
  selections: BetslipSelection[]
  addSelection: (sel: BetslipSelection) => void
  removeSelection: (marketId: string) => void
  updateStake: (marketId: string, stake: number) => void
  clearAll: () => void
  accumulatorStake: number
  setAccumulatorStake: (stake: number) => void
}

7.2 Currency Preference

Currency is tracked in URL search params (?currency=Latinum) per AGENTS.md deterministic URL state rule — NOT in client state. The CurrencyProvider simply reads from the URL.


8. Route Transition Map

graph TD
    ROOT["__root.tsx<br/>(always rendered)"]
    
    DASH["/ Dashboard<br/>Grid Overview"]
    QUAD_LIST["/quadrants<br/>Filtered Match List"]
    MATCH["/quadrants/$sectorId<br/>Live Match Detail"]
    
    LEDGER["/ledger<br/>Wager Overview"]
    ACTIVE["/ledger/active<br/>Open Wagers"]
    SETTLED["/ledger/settled<br/>Settled History"]
    
    FACTIONS["/registry/factions<br/>All Factions"]
    FACTION_D["/registry/factions/$id<br/>Faction Profile"]
    VENUES["/registry/venues<br/>All Venues"]
    VENUE_D["/registry/venues/$id<br/>Venue Profile"]
    
    SCHED["/schedule<br/>Upcoming Matches"]
    
    ROOT --> DASH
    ROOT --> QUAD_LIST
    ROOT --> MATCH
    ROOT --> LEDGER
    ROOT --> SCHED
    ROOT --> FACTIONS
    ROOT --> VENUES
    
    DASH -->|"click match card"| MATCH
    QUAD_LIST -->|"click match"| MATCH
    SCHED -->|"click scheduled"| MATCH
    
    LEDGER --> ACTIVE
    LEDGER --> SETTLED
    ACTIVE -->|"click match ref"| MATCH
    
    FACTIONS --> FACTION_D
    FACTION_D -->|"click active match"| MATCH
    VENUES --> VENUE_D
    VENUE_D -->|"click active match"| MATCH
    
    MATCH -->|"click market selection"| BETSLIP["Betslip (context, not route)"]

    style MATCH fill:#34d399,color:#000
    style BETSLIP fill:#fbbf24,color:#000
    style DASH fill:#38bdf8,color:#000