Skip to main content

Basic Usage

// Save
api.storage.set('my-key', { count: 42, items: ['a', 'b'] });

// Load
const data = api.storage.get('my-key');
// → { count: 42, items: ['a', 'b'] }

// Delete
api.storage.remove('my-key');
Use getForPlugin and setForPlugin to automatically namespace your keys:
// Automatically stored under "plugin:my-plugin:theme"
api.storage.setForPlugin(meta.id, 'theme', 'dark');
const theme = api.storage.getForPlugin(meta.id, 'theme');
// → "dark"
This prevents key collisions between plugins without manual prefixing.

Common Patterns

Saving Element Positions

let currentApi = null;

export function setup(api) {
  currentApi = api;
  const container = api.container;

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

  // Save 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)
      });
    }
  });
}

Saving Lists

export function setup(api) {
  let items = api.storage.getForPlugin(meta.id, 'items') || [];

  function addItem(text) {
    items.push({ text, done: false, id: Date.now() });
    api.storage.setForPlugin(meta.id, 'items', items);
  }

  function removeItem(id) {
    items = items.filter(i => i.id !== id);
    api.storage.setForPlugin(meta.id, 'items', items);
  }
}

Saving Settings with Defaults

const settings = {
  is24h: api.storage.getForPlugin(meta.id, '24h') ?? false,
  showSeconds: api.storage.getForPlugin(meta.id, 'seconds') ?? true,
  theme: api.storage.getForPlugin(meta.id, 'theme') ?? 'dark'
};

// Update and save
function toggle24h() {
  settings.is24h = !settings.is24h;
  api.storage.setForPlugin(meta.id, '24h', settings.is24h);
}

Reacting to Storage Changes

// Listen for ANY storage change
api.bus.on('storage:change', ({ key, value, oldValue, pluginId }) => {
  console.log(`${key}: ${oldValue}${value}`);
});

// Listen for changes to your own plugin's storage
api.bus.on('storage:change', ({ key, value }) => {
  if (key === `plugin:${meta.id}:theme`) {
    applyTheme(value);
  }
});

Key Naming

When using plugin-scoped storage, you don’t need to prefix manually:
// ✅ Good — automatic scoping
api.storage.setForPlugin(meta.id, 'theme', 'dark');
api.storage.setForPlugin(meta.id, 'items', [1, 2, 3]);

// ⚠️ Manual prefixing (still works)
api.storage.set(`${meta.id}-theme`, 'dark');
api.storage.set('sticky-notes-list', notes);
The core registry uses board-plugins-registry — avoid that key.

Manual Prefix Keys (Legacy)

If you prefer manual prefixing (the older pattern), it still works:
// ✅ Good
api.storage.set('sticky-notes-list', notes);
api.storage.set('clock-24h', true);

// ❌ Bad — will collide
api.storage.set('data', notes);
api.storage.set('settings', { ... });

Storage Limits

localStorage has a ~5MB limit per origin. For larger data, consider:
  • Compressing before storing
  • Using IndexedDB
  • Storing only what’s needed