The profile screen is the account center reached from the metagame bottom navigation. It surfaces the player’s identity, the path to convert a guest session into a permanent claimed account, and a row of one-tap developer convenience tools used during testing. There is no separate cosmetic or trophy collection page wired up yet — the /collection route redirects to the unified ships screen, and the collection CSS scaffolding (tabs, filter pills, ship grid, captain grid, achievement progress, detail panel) ships in the bundle but no React component renders it. The claim account modal is a fullscreen overlay launched from the profile screen that sends a passwordless email magic link to upgrade a guest account into a claimed account.
Stats / variables tables
Profile screen sections (top to bottom)
Section
Visibility
Purpose
Player card
Always
Avatar, display name, account-state badge, admin badge, player ID, email
Claim account button
Guest accounts only
Opens the claim modal
Unlock all + Reset all row
Always
Two paired developer buttons with confirm step
Grant gems button
Always
One-shot gem injection developer button
Admin tools button
Admin role only
Navigates to the admin screen
Sign out button
Always
Bottom of page, ghost styling
Player card fields
Field
Source
Notes
Avatar
Static rocket glyph
Fixed for all players; no upload yet
Display name
Player profile
Tap to edit inline; 1-24 characters
Account-state badge
Player profile
Reads “GUEST” or “CLAIMED”
Admin badge
Player profile
Shown only when role is admin
Player ID
Player profile
First 12 characters shown; tap copies full ID to clipboard; copy confirmation lasts 2 seconds
Email
Player profile
Shown only when an email is on file
Display name rules
Rule
Value
Minimum length
1 character
Maximum length
24 characters
Trimming
Leading and trailing whitespace stripped before validation
Error on invalid length
”1-24 characters”
Save target
Players table, display_name column
Account states
State
Email
Persistence
How to enter
Guest
None
Anonymous session, device-local risk if signed out without claim
Max wallet, max pull tickets, one of every ship hull at five-star, one legendary of every mod template, every mod-grid cell purchased
Reset all
Two-tap with red warning panel
Calls the dev reset RPC, re-runs bootstrap
Wipes inventory, wallet, save to day-one defaults; match history preserved
Grant gems
None
Calls the grant dev currency RPC, replaces wallet from snapshot
Adds 50,000 gems
Admin tools
None
Navigates to the admin screen
None directly; admin screen has its own RPCs
Sign out
None
Clears auth session, clears all stores, immediately starts a fresh anonymous session
Server retains the prior player’s data; client moves to a new guest account
Claim account modal flow
Step
What the player sees
What the system does
Open
Heading “CLAIM YOUR ACCOUNT”, email input, send button, cancel button
Modal scrim is dismissible by tapping outside
Validate
Inline error if invalid
Email must contain @ after trim
Submit
Send button reads “SENDING…”
Calls the player store claim action which sends a Supabase magic link
Sent
Heading “CHECK YOUR EMAIL” with the entered email, “GOT IT” close button
Modal stays open until the player closes it; the actual claim completes when the player clicks the emailed link from any device
Link clicked
Auth state changes on next app load, welcome modal triggers so the player can set their callsign
Same anonymous player ID is upgraded server-side; existing progress is preserved
Collection CSS scaffolding (present in the bundle, no rendered component)
The collection.css file is imported by the profile screen and defines styling for an unbuilt collection grid. None of these UI elements render in the live profile screen today; they are reserved for a future collection page.
Category
Subcategories defined in stylesheet
Sub-tab selector
Generic tabbed bar with active highlighting
Captain filter pills
Horizontal scrollable pill row with magenta active state
Section header and subtitle
Cal Sans heading, Space Grotesk subtitle
Toast messages
Two variants: merge (cyan) and starup (magenta)
Item cards
Ships, captains, achievements share a single card layout
Star display
Amber filled stars, recessed empty stars
Action buttons
Three variants: merge (cyan), starup (magenta), claim (amber)
Ship grid
Five squares per row (one per rarity tier), grouped by hull class, with a small count badge in the top-right
Hull rarity cards
Four cards per row, taller aspect ratio, rarity initial label, gray question mark for unowned slots
Captain grid
Five squares per row, wrapping, with a star count badge in the bottom-right
Detail panel
Expanding panel under the grid when a square is tapped
Undiscovered list
Greyed list of locked entries
Achievement progress
Track plus fill plus claimed badge; complete fills with a cyan gradient
Collection CSS rarity-tier count
| Rarity tiers expected by the grid | 5 |
Sign-out behavior
Step
Effect
Tap sign out
Player store clears user, profile, save, pity; bootstrapped flag flips off
Navigation
Page navigates to the hub route
Auto re-init
Player store immediately starts a fresh anonymous session so the next screen has a valid guest account; without this the app would otherwise hang on the loading splash
How it works
The profile screen reads its data from the player store, which is the client-side projection of the bootstrap player RPC response. The profile object contains the player ID, display name, email, account state, role, analytics opt-in flag, and creation timestamp. The screen renders nothing until the profile is loaded; while bootstrap is pending it shows a “Loading profile…” placeholder. Display name edits are validated locally, written through the profile service to the players table, and reflected back into the store on success. Player ID copies use the system clipboard and flash a “Copied!” label for 2 seconds.
The two destructive developer buttons (unlock all and reset all) each have their own confirm panel. Tapping the button replaces it with a yellow or red warning panel and a yes/no pair; tapping yes runs the corresponding RPC and re-bootstraps every store from the canonical server response, so the on-screen wallet, inventory, ships, mods, and grid all swap in atomically. The grant gems button has no confirm step and grants 50,000 gems by calling the grant dev currency RPC then replacing the wallet from the returned snapshot.
The claim account flow runs entirely client-initiated up to send time, then becomes asynchronous: the magic link is consumed on whichever device the player clicks it on, the anonymous Supabase user is upgraded in place (same player ID, new email attached), and the auth state change listener in the player store re-runs bootstrap to refresh the profile to the claimed state. A welcome modal then fires once per claim so the player can set their callsign. The “welcome shown” guard lives in localStorage.
The sign-out flow is intentionally seamless. Signing out does not leave the player on a dead screen — it clears all state then immediately calls init again to mint a new anonymous session, so the hub re-renders for a fresh guest. The original account is not deleted; it remains on the server and can be reattached by signing into its claimed email if it had been claimed.
Interactions
Interaction
Result
Tap display name
Inline edit field replaces the name; autofocused; save button writes to the server then exits edit mode
Tap save with invalid length
Inline error appears, name not changed
Tap player ID
Full ID copied to clipboard, label reads “Copied!” for 2 seconds
Tap claim account
Claim modal opens fullscreen
Tap unlock all
Confirm panel replaces the button; second tap on yes runs the RPC
Tap reset all
Confirm panel replaces the button; second tap on yes runs the RPC
Tap +50K gems
Wallet store is replaced from the RPC response; no confirm
Tap admin tools
Navigates to the admin screen route
Tap sign out
Auth cleared, navigation to hub, new guest session started immediately
Magic link clicked on any device
Auth state change re-bootstraps the profile, welcome modal opens
What it does NOT do
It does not let the player change their avatar; the rocket glyph is fixed.
It does not show a cosmetic, ship, captain, or achievement collection — that screen is not yet wired up, only its stylesheet exists.
It does not show wallet balances directly; those live in the top bar.
It does not delete an account; sign-out only ends the local session.
It does not change the player ID when a guest claims; the same ID is upgraded.
It does not require a password at any step; the only sign-in path is the email magic link.
It does not gate the developer buttons by role; unlock all, reset all, and the gem grant are visible to every player. Only the admin tools button is role-gated.
It does not block the destructive buttons against a double-tap; both protect with a single confirm step but no rate limit.
It does not retry a failed unlock, reset, or gem grant automatically; failures only log to the developer console and the user must tap again.
It does not toggle the analytics opt-in from this screen, even though the profile service exposes that mutation.
It does not handle a paid-account or subscription state; only guest and claimed exist.