Bubble Card Tools
v1.1.0
Hi everyone!
Bubble Card Tools grows from a module storage system into a general purpose backend for module developers. A module is frontend code: it cannot reach a media server, run before the dashboard renders or call an outside endpoint. This release opens those doors, so a module can browse the Home Assistant media library, control media players with far more options than the standard services expose, run code during the frontend bootstrap, display artwork that only exists on the LAN or translate text on the fly.
Added
Bulk module reads
New bubble_card_tools/read_all_modules WebSocket command, with an optional names list (every module when omitted). A cold client used to issue one read per file, around 50 round trips. It now needs one. Files are returned as raw content only: the YAML is deliberately not parsed server side, since a module's code field is the whole bundle and shipping both the raw and the parsed tree would double the payload and add seconds to a cold boot. A missing or unreadable file is skipped instead of failing the whole batch, so one bad file cannot break a boot.
Early frontend modules (extra_module_url)
JavaScript dropped in <config>/bubble_card/extra_module_url/*.js is now served over HTTP and registered with the frontend as an ES module URL, so it executes during the frontend bootstrap, before the Lovelace panel and its cards render. This is a generic hook: the integration has no knowledge of what those modules do.
- A module YAML carrying an
extra_module_urlstring has it written out as<module-stem>.jsbefore the folder is scanned, so installing a module can provision its early script with no file for the user to drop in. - URLs are versioned with the file mtime (
?v=<mtime>) and the previous URL of the same file is unregistered on a redeploy, soindex.htmlnever accumulates stale entries. - Static serving uses cache headers. The versioned URLs make long lived browser caching safe, and it is what lets a module execute before the first paint: on remote access an uncached fetch delays it past the HA launch screen.
- Registration happens at setup, so an integration reload or a restart picks up newly deployed files.
frontendis now a manifest dependency. Failures here are logged and swallowed, they can never block the WebSocket API or the rest of the integration.
Music Assistant access
Home Assistant's Music Assistant integration exposes none of these through its services, so four new modules reach the mass client that integration already connected (nothing opens its own connection). Every command takes an optional config_entry_id, and without one the first loaded entry wins.
bubble_card_tools/ma_queue_items(queue_id,limit,offset): the full play queue item list, which never crosses the HA service layer, slim serialized to title, artists, duration and artwork through the MA image proxy.bubble_card_tools/ma_queue_command(queue_id,command):play_index,delete_item,move_nextandclear.bubble_card_tools/ma_recommendations: the server's whole Home screen, one row per recommendation folder (recently played, provider "made for you" playlists, mood flows), provider agnostic by construction.bubble_card_tools/ma_favorite_stateandbubble_card_tools/ma_favorite_set(uri): read and toggle the favorite ("like") flag, including the library item id thatremove_itemrequires. Music Assistant handles the provider work and forwards the flag to every provider mapping.
Authenticated LAN artwork proxy
New /api/bubble_card_tools/thumb?url=<image url> endpoint. Media integrations such as Jellyfin hand the frontend direct LAN URLs for their thumbnails, which remote devices can neither reach nor display over HTTPS (mixed content). Home Assistant can reach them, so the view fetches them server side and serves them on the HA origin. Security posture:
- authentication required, no anonymous access,
- targets restricted to private addresses (RFC1918, loopback,
.localand single label LAN hostnames), so it is a LAN artwork proxy and not an open relay, - image content types only, response size capped.
The view is registered once per process, guarded so an integration reload cannot register it twice.
Faithful Jellyfin browsing
New bubble_card_tools/media_browse (media_content_id) command, browsing through the same API client the Jellyfin integration already authenticated, but strictly parent to direct children, exactly what the Jellyfin web UI requests. Home Assistant's built in Jellyfin media source browses with recursive queries, which can surface series the Jellyfin UI does not show inside that library (merged or misplaced items become phantom folders full of unrelated seasons). Sorting is done server side, Jellyfin UI style, and playlists keep their user defined order rather than being re-sorted.
Server side translation
New bubble_card_tools/translate (text, target) command for Module Store content. The browser cannot always translate on its own: the on-device Translator API needs a secure context and third party endpoints enforce CORS, neither of which constrains Home Assistant.
- Google as the primary endpoint, with the Microsoft Edge translator as a fallback (its auth token is cached for about 8 minutes),
- a 5 minute cooldown after a rate limit response,
- a persistent cache in HA storage (
bubble_card_tools.translations, 2000 entries max, debounced writes) shared by every browser and device, so a given string is translated once for the whole installation.
This feature will be added natively in the Bubble Card v3.3.0 editor.
Enjoy this release, cheers! 🍻