Prerequisites

  • Phaser 3 project (any bundler or plain <script> tag)
  • A LightLeaderboard account, game, and API key
  • A modern browser — fetch and crypto.randomUUID() are natively available
CORS: LightLeaderboard's API allows browser requests from any origin. No proxy needed.

Submit a Score

Call submitScore when the game ends. The response contains the player's new rank — show it immediately in your game-over screen.

score.js JS
// Call this from your GameOver scene or score handler
async function submitScore(score, playerId, playerName) {
  const res = await fetch(
    "https://yourapp.com/api/v1/games/my_game/scores",
    {
      method: "POST",
      headers: {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        score,
        playerRefId: playerId,
        playerName,
        submissionId: crypto.randomUUID(),
      }),
    }
  );
  return res.json(); // → { rank: 3, score: 42000, playerName: "Alice" }
}

Use in a Phaser Scene

Mark your scene method async and await the result. Phaser scenes handle async methods fine — the scene won't freeze.

GameOverScene.js JS
// Inside a Phaser 3 Scene class
class GameOverScene extends Phaser.Scene {

  async showRank(score, playerId, playerName) {
    const data = await submitScore(score, playerId, playerName);

    this.add.text(400, 300,
      `You ranked #${data.rank}!`,
      { fontSize: "32px", color: "#a89cff" }
    ).setOrigin(0.5);
  }
}

Fetch & Display the Leaderboard

Fetch the top 10 in your leaderboard scene's create(). Render each entry with this.add.text().

LeaderboardScene.js JS
// Fetch and display top 10
async function getLeaderboard() {
  const res = await fetch(
    "https://yourapp.com/api/v1/games/my_game/leaderboard?limit=10",
    {
      headers: { "Authorization": "Bearer YOUR_API_KEY" },
    }
  );
  const { entries } = await res.json();
  return entries; // [{ rank, playerName, score }, ...]
}

// In a Phaser scene:
class LeaderboardScene extends Phaser.Scene {
  async create() {
    const entries = await getLeaderboard();
    entries.forEach((e, i) => {
      this.add.text(50, 80 + i * 36,
        `#${e.rank}  ${e.playerName}  ${e.score}`,
        { fontSize: "18px", color: "#ffffff" }
      );
    });
  }
}

Tips

  • Store your API key in a config.js file — never commit it to a public repo. For client-side games, consider routing submissions through your own backend if you want to keep the key secret.
  • Use crypto.randomUUID() for submissionId. This prevents duplicate submissions on retry. Falls back to Date.now().toString() in very old browsers.
  • Add ?period=weekly to the leaderboard URL for weekly reset rankings.
  • Pass seasonId in the score body to support tournament seasons.