Instant accounts: skip the login wall
3 min read
Picture a player landing on your game. They're curious, maybe from a link a friend shared. And the first thing you show them is a sign-up form: email, password, confirm password, verify your inbox. A huge chunk of them bounce right there, before they've seen a single second of the thing that's actually fun. You built a wall in front of your own game.
The problem isn't that accounts are bad. It's that you demanded one before earning it. Triggair flips the order: every player gets a real account instantly and anonymously, and names themselves later, if they want to.
Log in first, ask questions never (well, later)
tg.login() mints an anonymous player and manages the token for you: it's stored and auto-refreshed, so the player stays signed in across sessions without ever typing a password.
import { createClient } from '@triggair/sdk';
const tg = createClient({ key: 'tg_pk_your_key' });
await tg.login(); // anonymous player minted; token auto-managed + refreshed
That's the whole onboarding. From this point the player is real: they can earn stats, submit to leaderboards, and get cloud saves that follow them across devices. No form, no email, no wall.
They already have an identity
The anonymous player has a profile from the start. You can read it, and they can shape it whenever they feel like it.
const me = await tg.players.me();
// { id: 'plr_...', display_name: 'Player-7Q2K' }
// Later, after they've won a match, hit a high score, whatever,
// invite them to make it theirs.
await tg.players.updateProfile({ display_name: 'Ada' });
Notice the default display_name: they show up on leaderboards and in matches immediately, under a friendly placeholder. Setting a real name becomes a reward moment ("put your name on the board!") instead of a toll gate.
Show off other players
Because everyone's a real player, you can render anyone's public profile: leaderboard rows, match opponents, or a shared link.
const opponent = await tg.players.profile(opponentId);
// { display_name: 'Ada', stats: [{ key: 'wins', value: 14 }, { key: 'best_score', value: 9800 }] }
// Have a handle from a share link or @mention? Resolve it to a player.
const found = await tg.players.lookup('ada');
profile(id) returns the display name plus public stats, so a "view profile" screen is one call. lookup(handle) goes the other way: from a human-typed handle to the player.
The sequencing that wins
The point isn't to hide accounts forever. It's to move the ask to after the fun. Prompt for a display name when the player has something to be proud of:
async function onFirstWin() {
const me = await tg.players.me();
if (me.display_name.startsWith('Player-')) {
// Still on the default, so now's the moment to ask.
showNameYourselfPrompt();
}
}
A player who just won wants their name on the result. That's a completely different emotional context than a stranger staring at a signup form.
Going further
- Wrap
loginand degrade gracefully. Every error is typed with acodeand anagentHint; if login fails, you can still show a read-only view rather than a blank screen. - Keep the placeholder friendly. The default
display_nameappears publicly, so it's designed to be presentable on day one instead of a raw ID. - Name-setting is opt-in. Some players will happily stay
Player-7Q2Kforever, and their saves and ranks work exactly the same. Don't force it.
Remove the wall and more players reach the fun. And players who reach the fun are the ones who stick around to name themselves. Start every session with tg.login() and let identity grow into the game instead of gating it.