openfrontio / openfrontio/OpenFrontIO
Subscribers with an unclaimed username are never prompted to claim one
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 1.4k
- Avg merge
- 17h 43m
- Merged PRs (30d)
- 310
Description
**Problem**
A subscriber with `usernameStatus: premium` and `username: null` is entitled to a
custom verified username and is never told so. The only place to claim one is the
username panel inside the account modal, which they have no reason to open.
This matters most for players who acquired a subscription as part of something
else rather than by deliberately subscribing — they don't know they have the
perk, and the subscription is spending down while they don't know.
The verified-name toggle beside the username input already routes them correctly:
```ts
if (status === "premium" || status === "indefinite") {
// Subscribed but no usable name yet (never set, or TEMPORARY####):
window.location.hash = "modal=account";
return;
}
```
But it renders in the same dim grey whether the player is ineligible (no
subscription) or eligible-but-unclaimed (one tap from their name), so nothing
signals that it does anything.
**Proposed fix**
*Boot prompt.* `Main.ts` already interrupts boot for a username problem — the
`TEMPORARY####` rename — guarded by `cleanHomepage` so it never hijacks a join
link or a deep link, and already priority-ordered ahead of the rewards popup. The
never-claimed case is a sibling condition on that same branch:
`premium && username === null`, different copy, same deep-link into the account
modal. No new gate, no onboarding flow.
*Pre-fill.* Open the username panel pre-filled with the sanitised platform
persona where one exists (see #5088), and show availability before submit. The
friction that stops people claiming is thinking of a name, not tapping accept.
Checking before submit also matters because a *successful* claim starts a 30-day
rename cooldown, so getting it wrong is expensive. (Failed claims are free — the
transaction throws before `usernameChangedAt` is written.)
*Handle the taken case as a normal path, not an error.* Bare names collide
constantly for common handles. Offering `base.1234` in the same screen as a
one-tap alternative requires the server-side fallback change tracked separately
in `infra`; without it a premium claim on a taken name is a 409 dead end.
*Decay.* The `TEMPORARY####` prompt fires every clean boot because it is a broken
state. Never-claimed is not broken — it is a perk not yet taken. Fire once, then
fall back to a standing affordance: render the verified toggle in an "action
needed" state for premium-but-unclaimed players rather than the same dim grey
used for "no subscription".
**Also needs deciding: first-boot modal ordering**
A player who receives a subscription grant also receives signup-bonus rewards, so
the rewards popup and this prompt both want the screen on the same clean boot.
The existing branch resolves a two-way race with a bare `return`, deferring
rewards a boot. Adding a third contender to that should be sequenced
deliberately — suggested: username first, rewards immediately after in the same
session, rather than inheriting the `return`.
Contributor guide
Research direction
Start in Main.ts at the existing TEMPORARY#### clean-boot prompt, then trace the account modal's username panel and verified-name toggle. Review #5088 for persona prefill and the separately tracked infra fallback before deciding the implementation boundary. Done means an unclaimed premium subscriber is prompted once, sees a prefilled available name when possible, gets an action-needed affordance afterward, and has deliberate rewards ordering.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100