identity.StartGuest(ctx)
Fires here, silently, before a single question is answered. VerifyPhoneCode(ctx, phone, code, guest *UserID) only preserves the user_id if a guest row already exists and has already accumulated something. Mint it at the signup prompt instead and the "keep this score" promise on screen 4 is empty.
creator link → challenge payload
Creator mechanics, the share token, the score-to-beat lookup. None of it is written. The handle, the 8/10 and the prize line are invented by this prototype.
trivia: questions, rounds, scoring
The entire acquisition layer is unwritten. No question bank, no round object, no timer scoring, no persistence. This screen runs on four hardcoded strings.
correct = BLUE, never green
Blue is the positive colour in this system and there is no green and no amber in the palette. Every state also carries the word, because the token file's hard rule is no state by colour alone.
share loop, weekly board, display names
Sharing is unwritten. So is the weekly leaderboard — and identity has no display name at all today, so a real leaderboard would currently be a list of UUIDs. That's why "@MercyOnTheMic" needs the handle decision on screen 4.
the score is already attached to a user_id
Because StartGuest ran on screen 1, this 9/10 belongs to a real row. Screen 4 doesn't create the player — it upgrades one that already exists.
identity.RequestPhoneCode → VerifyPhoneCode(…, guest)
Passing the guest flips the same row GUEST → REGISTERED, keeps the user_id, and rotates the session. The 9/10 survives because it was never anonymous.
no merge, ever
A correct code for a number that already belongs to someone returns that account and leaves the guest untouched. Someone who signs in on a friend's number does not absorb the friend — so this screen must never promise a merge.
handle, SMS code screen, contest entry
Decided: a free-text handle captured during phone verification. Needs a uniqueness rule and a moderation rule. Not drawn here — prototype 1 stops at the ask.
Open this on a phone and it fills the screen — there is no fake bezel and no fake status bar, because on a real device those are just wasted pixels. The frame you are looking at now only exists above 900px.
The guest session mints on screen 1, not screen 4. VerifyPhoneCode only preserves a user_id when a guest is passed in, and that guest row has to already hold the score. Get the order wrong and screen 4's whole promise — keep this score — is one the backend cannot honour.
Real, merged on main: guest sessions, phone OTP, session rotation, the no-merge rule, pick'em contests, kickoff lock, settlement, leaderboard ranking, the scoring engine and its ingest spine.
Invented by this file: the whole trivia layer, creator links and sharing, the weekly board, display names, and every pixel here. There is also no HTTP transport on any Go module yet.
100dvh so a collapsing Android URL bar cannot push the primary button off-screen.Not a design decision yet. This is a prototype to argue with, not a spec. What survives a real person's hands becomes ticket-d003.