velven
Docs
Menu

Add a leaderboard to your game in 10 minutes

Give your browser game a hosted leaderboard. You declare a board, post a score when a run ends, and draw the top 10. You test it on your laptop first, then on Velven. You need a game whose runs end with a score, and a Velven account.

View guide as Markdown

Declare the board

Add these 3 tags to your page's <head>, with your own Velven handle in the first:

index.html
<meta name="velven" content="@handle"><script type="application/velven+json">{"boards":[{"key":"main","trust":"client","min":0,"max":100000,"cooldown":5}]}</script><script src="https://velven.ai/sdk/v1.js"></script>
  • The <meta> tag is the proof tag: it names you as the creator.
  • The block declares one board, main. "trust":"client" lets the page post its own scores; without it the board takes scores only from your own server, and the page's posts answer server_only.
  • min, max and cooldown refuse a score out of range, or one sent less than 5 seconds after the last. Set them to fit your game.
  • The script loads the SDK as the global Velven.

Board fields lists every other field, such as sort for a board where lower is better.

Post the score and draw the board

Add a list for the board and a sign-in button to the page, then this script. Call onRunOver from your game when a run ends.

index.html
<ol id="board"></ol><button id="sign-in" hidden>Sign in to be ranked</button><script>  const board = document.getElementById("board");  const signInButton = document.getElementById("sign-in");  async function drawBoard() {    const top = await Velven.scores.top({ limit: 10 });    if (!top.ok) return;    board.replaceChildren(); // rows are other players' data: text only, never markup    for (const row of top.rows) {      const li = document.createElement("li");      li.textContent = `#${row.rank} @${row.user.handle} ${row.value}`;      board.append(li);    }  }  // Your game calls this when a run ends.  async function onRunOver(points) {    const result = await Velven.scores.submit(points);    if (!result.ok && result.error === "signed_out") signInButton.hidden = false;    await drawBoard();  }  // Ask a guest to sign in from a button, never on load.  signInButton.addEventListener("click", async () => {    const auth = await Velven.signIn();    if (auth.ok) signInButton.hidden = true;  });  Velven.ready().then((environment) => {    if (environment !== "site") drawBoard();  });</script>

A guest's score answers signed_out and is not stored, so the button offers sign-in. Examples has a complete page, with the player's own row under the top 10.

Test it on localhost

Serve the folder from any local server, such as:

Terminal
python3 -m http.server 8000

Then open http://127.0.0.1:8000/?velven_user=alice. On 127.0.0.1 and localhost the SDK answers with fakes, so nothing is listed or stored:

  • The board starts with 3 seeded players, so it has rows to draw.
  • ?velven_user=alice signs in a fake player. Play a run, and @alice joins the board at her rank.
  • Without ?velven_user, a run answers signed_out and your sign-in button shows. Locally it stays a guest.
  • A reload empties the board.

Local testing has more switches, such as ?velven_seed= to give the seeded players values like your game's.

List and prove the space

Deploy the page to a supported host and list it by following the quickstart. The proof tag you added in step 1 proves the space is yours, and Velven reads the board from the block when it lists the space.

Scores work once the space is published with you as its verified owner. Until its clip lands, the space is Processing, and score calls answer unavailable.

Note: Listed the space before you added the block? Deploy, then press Sync now in the Leaderboards section of the space's edit page. Velven also reads the block on its background check every 6 hours.

Play on Velven and see your row

Open your space on velven.ai, signed in, and play a run. When it ends, your handle appears on the board your page draws, at its rank.

The Leaderboards section of the space's edit page shows the newest submissions, with Delete and Ban beside each.

Nothing on the board? Troubleshooting goes through each error a score call can answer.

Next steps