Persist and retrieve plugin state using the element interaction storage system — how element hashes work and what resets state
Plugin storage is backed by the same element interaction system that built-in elements like multichoice, wordbank, and mathresponse use. Understanding how that system works — specifically how element hashes are computed — is essential to predicting when stored state persists and when it resets.
Declare "storage" in your manifest's permissions field before using any storage method:
Every plugin element is assigned a stable content hash derived from its attributes and body content. Storage is keyed by the composite (user_id, internote_id, element_hash), so state is automatically per-student, per-internote, per-element — you never need to include the hash in your storage keys manually.
The hash is available as InitContext.elementHash if you need to reference it directly:
Changing any attribute or body content in Chalk changes the hash and makes previously stored state inaccessible. This mirrors the behaviour of native interactive elements — editing a multichoice question resets student answers for the same reason. Inform educators of this in your plugin description.
An educator who edits a plugin element's attributes after students have started using the internote will effectively reset their progress on that element.
Retrieves a value previously saved with storage.set. Returns null if nothing has been stored at that key for this user and element.
key (string; required). The key to retrieve.Promise<unknown | null>Saves a value under a key. Overwrites any existing value at that key. The value must be JSON-serialisable.
key (string; required). The key to write.value (unknown; required). The value to store. Objects, arrays, strings, numbers, and booleans are all valid. Functions, undefined, and circular references are not.Promise<void>Removes a saved key. Has no effect if the key does not exist.
key (string; required). The key to remove.Promise<void>Removes all keys saved by this plugin for the current user at this element hash.
Promise<void>storage.clear() permanently removes all data this plugin has stored for the current user on this element. Do not call it in response to a user-facing action without a confirmation step.
storage.set rejects if writing would exceed this limit — always catch the erroronUnload is not guaranteed to fire in all termination scenarios. Save state on a debounced interval rather than relying solely on unload: