The Element SDK is in beta and not yet publicly released — APIs may change without notice.
Persist per-element state across sessions using api.storage
Every element gets a namespaced key/value store at api.storage. Use it to persist user state — quiz answers, slider positions, simulation settings, anything that should survive a page reload.
A checkbox that remembers whether it has been ticked:
Access the store via api.storage in any render function:
Retrieves a stored value. Returns null if nothing has been saved at that key for this user and element.
key (string) — the key to retrieve.Promise<T | null>Saves a value. Overwrites any existing value at that key. The value must be JSON-serialisable — objects, arrays, strings, numbers, and booleans are all valid. Functions and circular references are not.
key (string) — the key to write.value (T) — the value to store.Promise<void>Removes a saved key. Has no effect if the key does not exist.
key (string) — the key to remove.Promise<void>State is scoped to the current user, the current internote, and this element instance. The element instance key is derived from a content hash of the element's Chalk attributes and body — not from a position or index. This means:
This mirrors the behaviour of built-in interactive elements like multichoice — editing the element's Chalk effectively resets student progress. Document this in your element description so educators are aware.
Load saved state in a useEffect and apply it before or after calling anything that needs it:
For high-frequency updates (slider dragging, text input), debounce the save to avoid excessive writes:
In preview or server-rendering contexts, no storage backend is mounted and api.storage falls back to a no-op implementation — reads return null, writes resolve silently. Elements always render correctly; they just start in their default state. You do not need to guard against missing storage.
api.storage is the plugin-facing key/value API. api.interaction is the lower-level store that api.storage builds on — it persists state as an opaque blob keyed by the element hash. Use api.storage unless you have a specific reason to use api.interaction directly.