PURPOSE
Root React component for the metagame shell. Boots telemetry, remote error reporting, feature flags, player auth/bootstrap, and asset preload before rendering the app under BrowserRouter. Renders a themed loading screen with progress bar and a connection-error retry/offline-mode panel until bootstrap and asset preload complete.
OWNS
App— root component, runs boot orchestration in a singleuseEffectkeyed oninit.PerfTestRedirect— internal component mounted insideBrowserRouterthat navigates to/games/starship-survivors/playwhenPERF_FLAGS.perftestis set.ConnectedToast— internal floating toast shown when the offline-mode recovery loop re-establishes the Supabase connection. Auto-dismisses after 3 seconds.- Local UI state:
assetsReady(boolean),preloadPct(0..1),preloadStarted(ref guard preventing double-preload). - Loading-screen markup, error/offline panel, version stamp (
BUILD_VERSION), and spinner/progress-bar CSS keyframes (sp-spin,sp-pulse). beforeunload/pagehidewindow listeners and their cleanup.
READS FROM
usePlayerStoreselectors:bootstrapped,loading,bootstrapError,showWelcome,init,enterOfflineMode,recoveryToast,dismissRecoveryToast.@starship-survivors/engine/core/config—BUILD_VERSION,PERF_FLAGS.window.location.pathnamefor the nebula-viewer bypass (/nebula-viewer).useNavigate/useLocationfromreact-router-dom(used insidePerfTestRedirect).
PUSHES TO
startTelemetrySession,flushTelemetryQueue,endTelemetrySession,sendPartialRunOnUnload,Sampler.setSession(from@starship-survivors/engine/telemetry).initRemoteErrors(trackEvent)(from@starship-survivors/engine/core/remote-errors).hydrateFeatureFlags(from../services/featureFlags).preloadAllAssetswith a progress callback (from@starship-survivors/engine/core/preload).init()/enterOfflineMode()/dismissRecoveryToast()onusePlayerStore.flushAnalyticsSyncon the unload handler.- DOM: registers
beforeunloadandpagehidelisteners onwindow.
DOES NOT
- Does not implement auth, bootstrap RPC, store hydration, or wallet/inventory logic — that lives in
playerStore.init. - Does not define routes — that is delegated to
Routesfrom./routeswrapped inLayoutfrom./Layout. - Does not render any in-game canvas or HUD; only the metagame shell, modals (
WelcomeModal), FAB (FeedbackFAB), banner (UpdateBanner), and recovery toast. - Does not block the nebula viewer route on bootstrap —
/nebula-viewerbypasses the loading gate. - Does not retry telemetry or feature-flag hydration on failure (fire-and-forget).
- Does not amend or persist user state on unload — only flushes telemetry/analytics and ends the telemetry session.
Signals
loading || !bootstrapped || !assetsReady(with!isNebulaViewer) → renders the loading screen with spinner + progress bar.bootstrapErrortruthy → swaps spinner for a CONNECTION ERROR panel with RETRY and PLAY OFFLINE buttons.showWelcometrue → renders<WelcomeModal />inside the router.recoveryToasttrue → renders<ConnectedToast onDone={dismissRecoveryToast} />.PERF_FLAGS.perftesttrue → mounts<PerfTestRedirect />, which callsnavigate('/games/starship-survivors/play', { replace: true })if not already there.preloadAllAssetsprogress callback drives the loading-screen progress bar viasetPreloadPct.
Entry points
- Default export: none. Named export
Appis the metagame entry consumed by the metagame bundle entry point. PerfTestRedirectandConnectedToastare file-local and not exported.
Pattern notes
- Single boot
useEffectwithinitin the dependency array;preloadStartedref prevents the asset preload from running twice on effect re-run. - Telemetry, remote errors, feature flags, and player init are kicked off in parallel; only player bootstrap (
init) and asset preload gate the render. Telemetry/remote-errors/feature-flags are fire-and-forget. BrowserRouteris mounted only after bootstrap and asset preload succeed, so routing hooks are never invoked during the loading state.- Unload handler uses
sendPartialRunOnUnload,flushAnalyticsSync, andendTelemetrySession— the sync variants — so the browser does not cancel the requests during teardown. Registered on bothbeforeunloadandpagehide. - Nebula viewer (
/nebula-viewer) is a deliberate bypass: it reads archetype data only and does not require an authenticated player or hydrated stores. - Error panel offers two recovery paths:
init()retry andenterOfflineMode(). Offline mode is documented inline as “skips cloud save.” - Provider topology is minimal:
BrowserRouterwrapsLayoutwrapsRoutes. There is no Context provider tree above the router; global state is Zustand stores accessed directly. - Inline CSS keyframes are injected via a
<style>tag inside the loading subtree rather than a global stylesheet. ConnectedToastuses a fixed-position floating div withpointerEvents: 'none'andzIndex: 9999; auto-dismiss is a singlesetTimeout(onDone, 3000)with cleanup.