velven
Docs
Menu

Examples

Two examples for a game called Orbit Dodger, one for each tier: a complete single page, and the scoring module of a bundled game. Both use one board, main.

View guide as Markdown

Client tier, one page

A single page that loads the script tag and posts from the page. It draws its board on the game-over screen.

index.html
<!doctype html><html><head>  <meta name="velven" content="@mara">  <script type="application/velven+json">  {"boards":[{"key":"main","trust":"client","metric":"points","sort":"desc","min":0,"max":100000,"cooldown":5}]}  </script>  <script src="https://velven.ai/sdk/v1.js"></script></head><body>  <canvas id="game"></canvas>  <ol id="board"></ol>  <button id="sign-in" hidden>Sign in to be ranked</button>  <script>    const board = document.getElementById("board");    const signIn = 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      const line = (text) => { const li = document.createElement("li"); li.textContent = text; board.append(li); };      for (const r of top.rows) line(`#${r.rank} @${r.user.handle} ${r.value}`);      if (Velven.user) {        const mine = await Velven.scores.mine();        if (mine.ok && mine.row) line(`You: #${mine.row.rank} with ${mine.row.value}`);      }    }    // The game fires this when a run ends; the score is the run's points.    addEventListener("game:over", async (event) => {      const result = await Velven.scores.submit(event.detail.points);      if (!result.ok && result.error === "signed_out") signIn.hidden = false; // a guest: offer sign-in, never force it      await drawBoard();    });    // Sign-in from a button, never on load.    signIn.addEventListener("click", async () => {      const auth = await Velven.signIn();      if (auth.ok) signIn.hidden = true;    });    Velven.ready().then((environment) => {      if (environment !== "site") drawBoard(); // "velven" inside Velven, "local" on your laptop    });  </script></body></html>

Server tier, bundled

A bundled game that posts through its own function, the one in Server scores.

game.js
import { Velven } from "@velven/sdk";const post = (path, body) =>  fetch(path, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) });export async function onRunOver(points) {  const auth = await Velven.signIn(); // the player finished the run, so the card may show  if (auth.ok) {    // Your function verifies the token, then posts to Velven with the secret.    await post("/api/score", { token: auth.token, value: points, request_id: crypto.randomUUID() });  }  const top = await Velven.scores.top({ limit: 10 });  if (top.ok) drawBoard(top.rows, top.trust); // trust is "server" here; say so on the board}Velven.onAuth((user) => showName(user.handle)); // a later sign-in, through the card or another button

Note: In a React app with a component of its own named Velven, import the SDK under another name: import { Velven as sdk } from "@velven/sdk".