Small idle or casual game with one save: use saveData, loadData, and forceSyncData.
Beginner Flow
One save first, named slots later, sync when safe.
PersistlyGameSaves keeps normal game code focused on player state. The SDK writes locally first, then syncs through Persistly when policy and gameplay timing allow.
Recommended Path
Use the game-save facade first.
Most small games only need a runtime key, local storage, and saveData/loadData. Persistly still uses the default autosave slot behind the simple API.
Initialize PersistlyGameSaves once when your game boots.
See setupSave locallyWrite one-save game progress with saveData, or use saveSlot when the game has multiple saves.
Stay hereSync when safeForce-sync at pause, checkpoint, manual save, level complete, or another non-combat moment.
Review syncReal game flowsSee anonymous, signed-in, cross-browser, account-data, and cleanup examples.
Open scenariosCopy a starterUse the template center when you want a small service wrapper before reading all SDK pages.
Open templatesPaste-First Starters
Choose the smallest template before adding custom save architecture.
Start with one save for idle/casual games. Move to manual slots when players choose campaigns or save files. Add account/session handling when you need cross-device restore.
Beginner Example
Use the shared singleton from your game code.
The save is written locally first. Remote sync happens according to policy, or when your game calls forceSyncData at a safe point.
import { PersistlyGameSaveStatus, PersistlyGameSaves } from "@persistlyapp/sdk";
await PersistlyGameSaves.configure({
runtimeKey: "ps_test_replace_me",
});
const loaded = await PersistlyGameSaves.shared.loadData();
if (loaded.status === PersistlyGameSaveStatus.LocalFound && loaded.data) {
console.log("Boot from local data:", loaded.data);
} else {
console.log("Start new game.");
}
// Local write. This does not need a network request.
await PersistlyGameSaves.shared.saveData({
level: 5,
coins: 1200,
checkpoint: "forest-gate",
}, {
slotInfo: { characterName: "Astra", slot: "main" },
});
// First sync creates a Persistly account + slot if needed.
const sync = await PersistlyGameSaves.shared.forceSyncData();
if (sync.status === PersistlyGameSaveStatus.Synced) {
console.log("Synced to Persistly.");
}
if (sync.status === PersistlyGameSaveStatus.Conflict) {
console.log("Show a local-vs-cloud recovery UI.");
}Player Reference
playerRef is optional and not authentication.
Use playerRef only as a non-secret reference from your game or backend. It is not an auth identity, recovery key, or public lookup key.
What This Hides
The simple API still uses the durable cloud-save contract.
You can start with one default autosave slot and grow into named slots, accounts, slots, or authenticated accounts without changing the underlying Persistly model.
Game with manual saves or multiple slots: use saveSlot(slotId), loadSlot(slotId), and forceSync(slotId).
Game with account login, shared inventory, premium balances, or cross-device restore: use the account/session helpers as well.
Configure PersistlyGameSaves once when your game boots.
For one-save games, save progress with PersistlyGameSaves.shared.saveData.
Load that same save on the next launch with PersistlyGameSaves.shared.loadData.
Call PersistlyGameSaves.shared.forceSyncData at safe moments such as manual save, pause, checkpoint, or level complete.
The SDK keeps the local draft, cloud identity, and sync timing out of your normal game loop.
Named slots keep game code stable when the game grows into manual saves, multiple campaigns, or slot slots.
The lower-level runtime client still exists for custom integrations, but it is not the first path for shipped games.
Go Deeper
Advanced Runtime/API is secondary to the beginner flow.
Browser and package details around the same simple game-save facade.
Open JS notesAccount save patternSee how simple slots can grow into account-wide data and multiple slots.
Read patternAdvanced runtime APIUse direct endpoints only for custom SDKs or lower-level save primitives.
View reference