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.
localStorageflags 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
navigatefor/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
replaceFromSnapshotafter the dev currency RPC. - Bonus store: bonus-bar advance, reset-if-full, pending-reward shift.
- Onboarding store via
completeBeatafter a prologue beat resolves. - Post-FX store via
setPostFxValuefrom 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/BottomNavshell 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-idattributes 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
busyReflatch 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_KEYguard, 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.