JavaScript Templates

JavaScript templates for one-save, slots, and account restore.

Use @persistlyapp/sdk through PersistlyGameSaves first. Start with saveData for one current save, move to saveSlot for named slots, and attach a known account session when your own sign-in flow restores players across devices.

One SaveMultiple SlotsAccount + Slots

One Save

JavaScript one-save starter

When to use this: Use this for idle, casual, and prototype games that keep one current save.

JavaScript starter

JavaScript one-save starter

Copy this into your game-facing save service, then adapt the data type and safe sync moments to your game.

TYPESCRIPT
import { PersistlyGameSaveStatus, PersistlyGameSaves } from "@persistlyapp/sdk";

await PersistlyGameSaves.configure({
  runtimeKey: "ps_test_replace_me",
});

export async function saveGame(gameState: Record<string, unknown>) {
  await PersistlyGameSaves.shared.saveData(gameState);
}

export async function loadGame() {
  const loaded = await PersistlyGameSaves.shared.loadData();
  return loaded.status === PersistlyGameSaveStatus.LocalFound ? loaded.data : null;
}

export async function syncAfterCheckpoint() {
  return PersistlyGameSaves.shared.forceSyncData();
}

Persist your normal game state through saveData.

Read local state first with loadData so the game can boot offline.

Call forceSyncData from pause, checkpoint, manual save, or level-complete moments.

Multiple Slots

JavaScript multiple-slot starter

When to use this: Use this when the game has manual saves, campaigns, save files, or character selection.

JavaScript starter

JavaScript multiple-slot starter

Copy this into your game-facing save service, then adapt the data type and safe sync moments to your game.

TYPESCRIPT
import { PersistlyGameSaveStatus, PersistlyGameSaves } from "@persistlyapp/sdk";

await PersistlyGameSaves.configure({
  runtimeKey: "ps_test_replace_me",
});

export async function saveCampaign(slotId: string, gameState: Record<string, unknown>) {
  await PersistlyGameSaves.shared.saveSlot(slotId, gameState, {
    slotInfo: { label: slotId },
  });
}

export async function loadCampaign(slotId: string) {
  const loaded = await PersistlyGameSaves.shared.loadSlot(slotId);
  return loaded.status === PersistlyGameSaveStatus.LocalFound ? loaded.data : null;
}

export async function syncCampaign(slotId: string) {
  return PersistlyGameSaves.shared.forceSync(slotId);
}

Choose stable developer slot ids such as autosave, slot-1, slot-2, or warrior.

Keep menu labels and timestamps in slotInfo so save selection UI can stay fast.

Sync the active slot from safe lifecycle or manual-save points.

Account + Slots

JavaScript account + slots starter

When to use this: Use this when your own sign-in flow stores and restores the Persistly account session.

JavaScript starter

JavaScript account + slots starter

Copy this into your game-facing save service, then adapt the data type and safe sync moments to your game.

TYPESCRIPT
import { PersistlyGameSaves } from "@persistlyapp/sdk";

await PersistlyGameSaves.configure({
  runtimeKey: "ps_test_replace_me",
});

export async function exportSessionForYourBackend() {
  await PersistlyGameSaves.shared.ensureAccount();
  return PersistlyGameSaves.shared.getAccountSession({ includeToken: true });
}

export async function restoreKnownAccount(accountId: string, accountSessionToken: string) {
  await PersistlyGameSaves.shared.attachAccount({
    accountId,
    accountSessionToken,
  });
}

export async function saveSignedInSlot(slotId: string, gameState: Record<string, unknown>) {
  await PersistlyGameSaves.shared.saveSlot(slotId, gameState, {
    slotInfo: { label: slotId },
  });
  return PersistlyGameSaves.shared.forceSync(slotId);
}

Store accountId and accountSessionToken only in your trusted account system.

Restore with attachAccount before loading or refreshing signed-in slots.

Keep normal gameplay writes on saveSlot so account restore stays facade-first.