Skip to main content

Overview

api.storage is a thin wrapper over localStorage with automatic JSON serialization.
api.storage.set('my-counter', 42);
const count = api.storage.get('my-counter');  // → 42

API

api.storage.get(key)

Retrieve a value. Returns null if the key doesn’t exist.
const theme = api.storage.get('my-plugin-theme');
// → "dark" or null

api.storage.set(key, value)

Store a value. Automatically serializes to JSON. Emits a storage:change event.
api.storage.set('my-counter', 42);
api.storage.set('my-list', [1, 2, 3]);
api.storage.set('my-obj', { name: 'test', active: true });

api.storage.remove(key)

Delete a stored key.
api.storage.remove('my-counter');

api.storage.list()

Returns an array of all localStorage keys.
const keys = api.storage.list();
// → ['board-plugins-registry', 'my-counter', ...]

api.storage.clear()

Clears all localStorage data. Use with extreme caution.

Plugin-Scoped Storage

Instead of manually prefixing keys, use the plugin-scoped methods. They automatically prefix with plugin:{pluginId}:.

api.storage.getForPlugin(pluginId, key)

const theme = api.storage.getForPlugin(meta.id, 'theme');
// Reads from localStorage key: "plugin:my-plugin:theme"

api.storage.setForPlugin(pluginId, key, value)

api.storage.setForPlugin(meta.id, 'theme', 'dark');
// Writes to localStorage key: "plugin:my-plugin:theme"
The Sample Theme plugin uses setForPlugin/getForPlugin to persist theme settings with automatic key scoping.

Storage Change Events

Every set() and setForPlugin() call emits a storage:change event:
api.bus.on('storage:change', ({ key, value, oldValue, pluginId }) => {
  console.log(`${key} changed from`, oldValue, 'to', value);
  if (pluginId) console.log(`Changed by plugin: ${pluginId}`);
});
FieldDescription
keyThe storage key (full key, including plugin: prefix for scoped storage)
valueThe new value
oldValueThe previous value
pluginId(only for setForPlugin) The plugin that made the change

Best Practices

Use Plugin-Scoped Storage

// ✅ Good — automatic scoping, no collisions
api.storage.setForPlugin(meta.id, 'theme', 'dark');
api.storage.getForPlugin(meta.id, 'theme');

// ⚠️ Works, but manual prefixing
api.storage.set(`${meta.id}-theme`, 'dark');
api.storage.get(`${meta.id}-theme`);

Store Positions

// Save position on drag end
api.bus.on('plugin:dragend', ({ el }) => {
  if (el.dataset.pluginId === meta.id) {
    api.storage.setForPlugin(meta.id, 'pos', {
      left: parseInt(el.style.left),
      top: parseInt(el.style.top)
    });
  }
});

// Restore on load
const pos = api.storage.getForPlugin(meta.id, 'pos');
if (pos) {
  api.container.style.left = pos.left + 'px';
  api.container.style.top = pos.top + 'px';
}

Store Settings

// With defaults
const is24h = api.storage.getForPlugin(meta.id, '24h') ?? false;
const showSeconds = api.storage.getForPlugin(meta.id, 'seconds') ?? true;
api.storage uses localStorage, which has a ~5MB limit per origin. Don’t store large blobs (images, long documents) — use IndexedDB for that.
The core registry uses board-plugins-registry — avoid that key.