Skip to content

Feature Request : Store JSON in HA system level store #9

Description

@Ltek

I really love what you've built, and I'm building a set of cards that are complimentary. I'd like to allow the users to import the styles they create with your button-builder. In order to make it easy for users to do that, my ask is to store then using Home Assistant's built-in frontend storage API that solves this with no custom backend endpoints — I use it in my own cards and it's been rock solid. How it works...

HA exposes a per-instance key/value store over the WebSocket connection, backed by .storage on the server.

Two scopes:

  • system (frontend/{get,set,subscribe}_system_data) — shared across the whole instance/all users; admin-writable. Great for a shared library.
  • user (frontend/{get,set,subscribe}_user_data) — per-HA-user.

No custom_components endpoint, no REST view — the frontend just calls it through the existing hass.connection. It persists server-side and survives restarts.

Read + live-subscribe:

const data = await hass.connection.sendMessagePromise({
  type: 'frontend/get_system_data',
  key: 'button_builder_library',
});

// live updates: fires immediately with the current value, then on every change (any device)
hass.connection.subscribeMessage(
  (msg) => { applyLibrary(msg.value); },
  { type: 'frontend/subscribe_system_data', key: 'button_builder_library' }
);

Write:

await hass.connection.sendMessagePromise({
  type: 'frontend/set_system_data',
  key: 'button_builder_library',
  value: {
    button_builder_library: 1,          // version field for future migrations
    records: {                          // your saved designs, keyed by id/slug
      'my-neon-tile': { name: 'Neon Tile', folder: 'Tiles', tags: ['neon'],
                        updatedAt: 1732600000000, yaml: '…', config: { /* structured */ } },
    },
  },
});

value is any JSON-serializable object — keep your existing record shape ({id,name,folder,tags,updatedAt,yaml}) and just nest it under a versioned envelope.

How I use it... each of my cards keeps its library under its own namespaced key (e.g. ltek_button_styles), stores { : 1, presets: { : {...} } }, and subscribes so an edit on one dashboard re-renders every card on the instance instantly. A one-time migration copies any legacy localStorage entries up into the system store on first load, then reads from the store thereafter — so existing users lose nothing.

Why it's worth it for Button Builder:

  • Designs sync across devices/sessions/browsers automatically.
  • No backend work; it rides the WebSocket you already have.
  • It opens the door for other cards to read a shared library (I'm about to post major revamp-releases of two cards which could leverage Button Builder designs if they were readable this way).

Happy to share the exact migration snippet I use (localStorage → system_data, once) if helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions