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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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