# Cloud saves for PlayDrop games

Save and load player progress with sdk.me.appData and updateAppData, for guests and signed-in players, with the rules for writes, previews and offline play.

Source: https://www.playdrop.ai/create/learn/cloud-saves

Cloud saves keep each player's progress for your game on PlayDrop, so it follows them from the website to the apps. One JSON object per player and game is stored; no server or multiplayer room is needed.

## Read and write

After `init()`, `sdk.me.appData` is the saved snapshot: `{ data, seq, ts_event, ts_arrival }`, or `null` before the first save. Read your object from `data`. Write the whole object with `updateAppData`, which returns the saved snapshot and updates `sdk.me.appData`.

```js
const sdk = await playdrop.init();
let progress = { level: 1, coins: 0, ...(sdk.me.appData?.data ?? {}) };
let queue = Promise.resolve();

// Resolves with the saved snapshot; rejects when the save failed.
function save(changes) {
  progress = { ...progress, ...changes };
  const snapshot = { ...progress };
  const attempt = queue.then(() => sdk.me.updateAppData(snapshot));
  queue = attempt.catch(() => {}); // a failed save must not block the next one
  return attempt;
}

try {
  await save({ level: 2 });
  showSaved();
} catch (error) {
  showSaveError(); // progress stays in memory; the next save sends it again
}
```

- Each write replaces the entire saved object: keep every field you still need.
- Serialize writes, as above, so an older save never lands after a newer one, and keep the queue going after a failure.
- Show "Saved" only after the promise resolves. Changing `appData.data` in memory saves nothing.
- `appData` has no `get`, `set` or `save` methods.

## When to save

Save at checkpoints, level ends and purchases rather than every frame. Never save during previews or captures: only write when `sdk.host.phase` is `play`. Keep a save small and versioned with your own field, such as `saveVersion: 2`, so a later game version can migrate it.

## Guests and signed-in players

You do not need to check `sdk.me.isLoggedIn` before saving: PlayDrop guests keep their saves too. A player with no session at all keeps the save in memory for that visit, so a resolved write does not prove the save reached the cloud. Use `isLoggedIn` only for features that need a real account, such as purchases and hosted multiplayer.

## Offline

In a browser, saves need a connection and there is no offline queue: keep playing on failure and retry at the next checkpoint. Hosts that advertise device-data support, such as offline-capable PlayDrop apps, keep saves on the device and sync them when online.

## What saves are not

Saves are private to one player and one game. They are separate from [leaderboards](https://www.playdrop.ai/create/learn/leaderboards) and [achievements](https://www.playdrop.ai/create/learn/achievements), which have their own APIs and appear on PlayDrop. State shared between players, such as a match or a world, belongs on a [game server](https://www.playdrop.ai/create/learn/game-servers) in your game's MongoDB collections.

## Test

Saves belong to an uploaded game. Upload a private version at least once, then test from the receipt's `url` or from the local Dev frame described in [publishing from your AI app](https://www.playdrop.ai/create/learn/mcp-publishing).

## Related guides

- [Leaderboards](https://www.playdrop.ai/create/learn/leaderboards): Declare leaderboards in catalogue.json, submit scores with sdk.leaderboards and show top ranks and the player's neighbors. Score types, limits and update rules.
- [Achievements](https://www.playdrop.ai/create/learn/achievements): Declare standard and incremental achievements with icons in catalogue.json, unlock them and report progress with sdk.achievements.
- [Realtime game servers](https://www.playdrop.ai/create/learn/game-servers): Run a hosted Colyseus 0.17 server with a MongoDB database for your game, connect from the browser with the SDK, test with two players and know the limits.
