metagame/screens

PURPOSE — Top-level route screens for the metagame React UI. Each screen is a route-bound component mounted by the router; it composes the shell chrome (V32Shell / OnboardingShell / bespoke fullscreen), pulls reactive state from Zustand stores, calls services for server-authoritative mutations, and navigates to other routes (most commonly the play route, which exits the metagame entirely).

OWNS

  • Per-screen local UI state: planet swipe index, drag offset, transition / blackout timers, edit-mode flags, confirmation flags, busy/loading latches, error/toast messages, copy-feedback flags, picked mission postings, prologue beat advance, fullscreen overlay refs for the shop pull engine, on-demand fetch state for telemetry runs / render-perf rows / sessions, telemetry platform + date-range filters, viewer index + URL deep-link sync for archetype / background browsers, viewer keyboard handlers, post-FX panel toggles, bake status messages.
  • Imperative DOM handles inside the shop root: currency display nodes, bonus bar fills, milestone nodes, packs-grid HTML, delegated click handler bound to the shop root element.
  • A guarded entry wrapper on the perf dashboard that short-circuits to a stub outside dev mode so the service-role key path is tree-shaken from production builds.

READS FROM

  • Session store for selected ship + run-def slot.
  • Inventory store for hull unlock status and resolved ShipDef.
  • Onboarding store for prologue progress and current beat.
  • Player store for profile, role, guest/claimed state, sign-out.
  • Wallet store for gem balance, dev top-up snapshot reload.
  • Bonus store for bonus-bar points + milestone advance + pending reward queue.
  • Reward queue store to enqueue prologue beat rewards.
  • Post-FX store for the in-viewer FX panel sliders/toggles.
  • Data tables: nebula archetype list, planet archetype map, planet config + order, ship rarity colors and tier track palette, prologue beats, mission postings, pull-config banners + pull costs, all-backgrounds catalog.
  • localStorage flags for per-planet Challenge Mode unlock + popup-shown latch.
  • Vite env (import.meta.env.DEV, VITE_SUPABASE_SERVICE_KEY) for the perf dashboard guard.
  • Supabase REST directly with the service key for telemetry rows on the perf dashboard.

PUSHES TO

  • React Router navigate for /profile, /admin, root hub, and the play route once a run def is assembled.
  • Run-def assembly service to materialize a run from ship + planet + challenge flag.
  • Pull service for server-authoritative pull execution; shop service for gem-pack purchases; profile service for display-name updates; unlock service for the dev unlock/reset buttons; Supabase RPCs for admin grant/reset/wipe and the dev currency grant.
  • Shop pull-engine module: init/destroy lifecycle, startPull, closeLegendary, bonus-flare spawn, milestone node flash.
  • Wallet store via the replaceFromSnapshot after the dev currency RPC.
  • Bonus store: bonus-bar advance, reset-if-full, pending-reward shift.
  • Onboarding store via completeBeat after a prologue beat resolves.
  • Post-FX store via setPostFxValue from the in-viewer FX panel.
  • Nebula bake helper and background bake helper, which produce PNG bytes that the screen turns into anchor-click downloads.
  • Browser history (replaceState) to sync the viewer index back into the URL.

DOES NOT

  • Render the persistent top bar / currency strip / bottom tabs themselves — those live in V32Shell / BottomNav shell components and are composed by the screens.
  • Implement nebula rendering, background rendering, leaderboard layout, planet swiper card visuals, claim-account flow internals, progress-bar internals, update-banner internals, panel/modal chrome — all delegated to dedicated metagame components.
  • Drive the pull sequence visuals (card spawns, reveals, supernova, outro) — handed off to the imperative shop pull engine.
  • Mutate the wallet, pity, inventory, or fake-store audit trails locally — all such writes go through services that hit server RPCs, then store snapshots are replaced from the canonical response.
  • Decide pull rates, pity rules, gem-pack contents, mission posting pool, prologue beat order, nebula archetype list, or planet config — those are data tables, consumed read-only.
  • Authorize admin tools client-side beyond gating the route; the server RPCs verify role on every admin call.
  • Run the game loop, fixed-timestep tick, telemetry collection, or any in-run state.
  • Manage authentication — the screens read the player profile and call signOut; the auth flow itself is upstream.

Signals fired / Signals watched — none. Screens communicate via Zustand store subscriptions, direct service / RPC calls, router navigation, and DOM event delegation — they do not emit or subscribe to engine signals.

Entry points

  • HubScreen — home / launch screen with planet swiper, planet progress, Challenge Mode toggle, LAUNCH button that assembles a run def and navigates to play.
  • MissionBoardScreen — job-board view that picks two mission postings and routes the accepted one into the play flow.
  • ShopScreen — fullscreen storefront and pull surface; runs the imperative pull engine, hosts banners, gem packs, bonus bar, and the legendary deep-dive overlay.
  • ProfileScreen — account center with avatar, display-name edit, guest/claimed/admin badges, copy-ID, claim-account CTA, dev unlock/reset/grant buttons, admin entry, sign-out.
  • AdminScreen — admin-only debug tools for granting gems, resetting pity, and wiping a save through admin RPCs.
  • PrologueScreen — guided first-time experience driver; advances beats, grants beat rewards, and exits to hub on completion.
  • PerfDashboardScreen (default export, dev-only-guarded) — telemetry analytics dashboard with platform + date-range filters and on-demand render-perf load.
  • NebulaViewerScreen (default export) — fullscreen browser for the nebula archetype list with keyboard nav, info panel, post-FX panel, and frame-grid bake-to-PNG.
  • BackgroundsViewerScreen (default export) — fullscreen browser for tileable backgrounds with parallax / seam-debug / static / tiles-across toggles and a multi-size bake-to-PNG flow.

Pattern notes

  • Two shell families coexist: the standard metagame shell with persistent currency bar and bottom tabs, the onboarding shell for the guided first-time flow, and bespoke fullscreen layouts (shop, viewers, perf dashboard) that opt out of shell chrome entirely.
  • The shop is the only screen that drives DOM imperatively after mount: a delegated click handler on the shop root reads data-pack-id / data-pull-count / data-banner-id attributes so that pull and pack buttons keep working across re-renders that replace inner HTML.
  • All write paths are server-authoritative. Client never mutates currencies, pity, inventory, or audit logs directly; it calls a service that hits an RPC, then replaces the local store from the response snapshot. A busyRef latch guards against double-tap RPC duplication on shop pull + pack purchase.
  • Viewer screens share a small pattern: read the initial index from a URL query param, replace the URL on every index change, and bind keyboard shortcuts that ignore events originating from form inputs.
  • Sensitive code paths are guarded so production builds tree-shake them: the perf dashboard wraps its body in a DEV && SERVICE_KEY guard, and the admin screen returns an access-required stub if the loaded profile is not admin.
  • Challenge Mode unlock is per-planet and persisted in localStorage; the unlock banner has a paired shown-flag so it never reappears after the first dismissal.
  • The planet swiper coordinates touch + mouse drag through a shared origin ref, a rapid-flick override that snaps any in-progress animation to completion past the halfway mark, and a CSS-side spring-back when the drag falls short of the swipe threshold.