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.
Declare the board
Add these 3 tags to your page's <head>, with your own Velven handle in the first:
<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 answerserver_only. min,maxandcooldownrefuse 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.
<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:
python3 -m http.server 8000Then 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=alicesigns in a fake player. Play a run, and@alicejoins the board at her rank.- Without
?velven_user, a run answerssigned_outand 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
- Read past days and seasons for a daily or weekly board.
- Post from your own server when your server can check the run.
- Keep saves so players pick up where they left off.