Quickstart
The fastest way to see this working: upload any zip with an index.html at its root (see Upload a game ), then paste the snippet below into your game's JavaScript and adapt the applySaveData / showMessage / renderLeaderboard calls to whatever your game actually does. Nothing to install — window.DavidnetSDK already exists the moment your game loads.
1. Restore progress on load
Call getJsonBlob() once when your game boots. data is null if this player has never saved before — that's the normal case for a brand new player, not an error.
const { data } = await window.DavidnetSDK.getJsonBlob();
if (data) {
applySaveData(data);
} else {
startNewGame();
}2. Save progress on meaningful changes
Trigger this from game events — level-complete, checkpoint, inventory change — not from your render loop. See Save data for slots and size limits.
function onLevelComplete(levelIndex, inventory) {
window.DavidnetSDK.saveJsonBlob({ levelIndex, inventory }).catch((e) => {
console.warn("Could not save progress", e);
});
}3. Submit a score on game over
The server only ever keeps the player's HIGHEST score, so it's always safe to call this on every game over. See Highscores & leaderboards for multiple leaderboards per game.
async function onGameOver(finalScore) {
try {
const result = await window.DavidnetSDK.applyHighscore(finalScore);
if (result.isNewGlobalBest) showMessage("New world record!");
else if (result.isNewPersonalBest) showMessage("New personal best!");
} catch (e) {
console.warn("Could not submit score", e);
}
}4. Unlock an achievement
Call this once when the condition becomes true. See Achievements for progress-bar achievements.
async function onBossDefeated() {
const { isNew } = await window.DavidnetSDK.unlockAchievement({
id: "first_boss_kill",
name: "Giant Slayer",
description: "Defeat the first boss",
icon: "⚔️"
});
if (isNew) showMessage("Achievement unlocked: Giant Slayer!");
}Putting it all together
// Every one of these functions already exists on window.DavidnetSDK the moment your
// game loads - there is nothing to install or import, just call them directly.
// 1. Restore the player's progress once when the game boots.
async function restoreProgress() {
try {
const { data } = await window.DavidnetSDK.getJsonBlob();
if (data) applySaveData(data); // data is null if this player never saved before
} catch (e) {
console.warn("Could not load save", e);
}
}
// 2. Save progress whenever it changes meaningfully - on checkpoint/level-complete,
// NOT every frame (see Rate limits).
async function onCheckpoint(state) {
try {
await window.DavidnetSDK.saveJsonBlob(state);
} catch (e) {
console.warn("Could not save progress", e);
}
}
// 3. Submit a score on game over. The server only ever keeps your best, so this is
// always safe to call.
async function onGameOver(finalScore) {
try {
const { isNewPersonalBest, isNewGlobalBest } = await window.DavidnetSDK.applyHighscore(finalScore);
if (isNewGlobalBest) showMessage("New world record!");
else if (isNewPersonalBest) showMessage("New personal best!");
} catch (e) {
console.warn("Could not submit score", e);
}
}
// 4. Unlock an achievement ONCE when something happens - not every frame.
async function onBossDefeated() {
try {
const { isNew } = await window.DavidnetSDK.unlockAchievement({
id: "first_boss_kill", // you choose this - keep it short and stable
name: "Giant Slayer", // shown to the player
description: "Defeat the first boss",
icon: "⚔️"
});
if (isNew) showMessage("Achievement unlocked: Giant Slayer!");
} catch (e) {
console.warn("Could not unlock achievement", e);
}
}
// 5. Show the top 10 players, e.g. on a "leaderboard" button.
async function showLeaderboard() {
const { leaderboard } = await window.DavidnetSDK.getHighscores();
renderLeaderboard(leaderboard); // [{ rank, username, displayName, avatarUrl, score }, ...]
}Next steps
- Building a multiplayer game? Read Realtime multiplayer .
- Not writing plain JavaScript? Read Godot / other engines .
- Calling something often (a live leaderboard, frequent saves)? Read Rate limits first.