triggair

Blog / identity

Instant accounts: skip the login wall

3 min read

Instant accounts: skip the login wall cover art

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.

ts
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.

ts
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.

ts
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:

ts
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 login and degrade gracefully. Every error is typed with a code and an agentHint; if login fails, you can still show a read-only view rather than a blank screen.
  • Keep the placeholder friendly. The default display_name appears 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-7Q2K forever, 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.

Build this into your game.

Everything above is one import and a publishable key away. Start with the quickstart, or read the guide for the exact feature.

Keep reading