Saving and Loading Saves
Saving in Choicekit is about preserving a playable run exactly as the player left it: passage, state history, and deterministic randomness context.
In IF terms, a save is a branch checkpoint.
What gets persisted
Section titled “What gets persisted”A story save contains data needed to restore narrative execution, including:
- state and state history
- current passage position
- metadata used for deterministic replay
Plugin-level persistence concerns (like settings/achievements) are documented in Plugins.
Configure persistence
Section titled “Configure persistence”Use a persistence adapter through engine config.
import { ChoicekitEngineBuilder } from "choicekit";import { LocalStoragePersistenceAdapter } from "choicekit";
const engine = await new ChoicekitEngineBuilder() .withName("daves-adventure") .withPassages({ name: "Start", data: "..." }) .withVars({ gold: 0 }) .withConfig({ persistence: LocalStoragePersistenceAdapter, saveSlots: 10, autoSave: "passage", }) .build();Use a stable, unique engine name per story. Engines sharing a name share persisted keys.
Save slots
Section titled “Save slots”Choicekit supports:
- autosave slot
- numbered slots (
0tosaveSlots - 1)
Manual save/load:
await engine.saveToSaveSlot(2);await engine.loadFromSaveSlot(2);Autosave slot shortcuts:
await engine.saveToSaveSlot();await engine.loadFromSaveSlot();Load best available recent save:
await engine.loadRecentSave();Listing and deleting saves
Section titled “Listing and deleting saves”Build save UIs with getSaves():
for await (const save of engine.getSaves()) { if (save.type === "autosave") { console.log("autosave", save.data.savedOn); } else { console.log("slot", save.slot, save.data.savedOn); }}Delete saves:
await engine.deleteSaveSlot(); // autosaveawait engine.deleteSaveSlot(3); // slot 3await engine.deleteAllSaveSlots();Export and import
Section titled “Export and import”For cloud backup/share flows:
const exported = await engine.saveToExport();
// later, same device or another deviceawait engine.loadFromExport(exported);This is useful for player support, migration between devices, and beta testing reproduction.
Compression and save size
Section titled “Compression and save size”config.compress enables compact save payloads (recommended for large state/history).
Also keep vars focused on story facts, not transient UI state.
Save lifecycle events
Section titled “Save lifecycle events”You can hook save UX indicators and error handling with:
saveStart/saveEndloadStart/loadEnddeleteStart/deleteEnd
engine.on("saveStart", ({ slot }) => { console.log("saving", slot);});
engine.on("saveEnd", (event) => { if (event.type === "success") { console.log("saved", event.slot); return; } console.error("save failed", event.slot, event.error);});Common pitfalls
Section titled “Common pitfalls”- Missing persistence adapter: save/load/delete operations will fail.
- Changing state schema without migrations: old saves may become incompatible.
- Overloading vars with UI-only data: save payloads grow and become harder to evolve.
Next: see Save Migrations for versioning strategy.