Use authenticated brands proxy for repository icons#937
Open
Use authenticated brands proxy for repository icons#937
Conversation
The dashboard constructed icon URLs via the upstream `brandsUrl` helper
at a pinned submodule (3ffbd435, Jan 2025) that predates the
brands-proxy API introduced in HA 2026.3. After upstream rewrote
`brands-url.ts` to return `/api/brands/integration/{domain}/icon.png`
with an access token, custom integrations shipping inline brand assets
no longer render (the legacy CDN no longer accepts new custom
integration submissions).
Bump `homeassistant-frontend` to current master, drop the now-removed
`useFallback` parameter, and fetch/schedule the brands access token
from the dashboard's own bundle (module-level token state is
bundle-scoped, so HACS must populate its own copy). Clear the refresh
interval on disconnect.
Fixes hacs/integration#5171
Fixes hacs/integration#5223
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The HACS dashboard shows "icon not available" for custom integrations that ship inline brand assets (a feature introduced in Home Assistant 2026.3). Root cause is a combination of three things:
homeassistant-frontendsubmodule is pinned to3ffbd435(2025-01-09) — pre-brands-proxy.brandsUrl({...})still returnshttps://brands.home-assistant.io/_/{domain}/icon.png. That CDN no longer accepts new custom-integration submissions (see the brands-proxy API blog post), so custom-integration icons 404.useFallback: true— a parameter that has since been removed from upstreamBrandsOptions, so a naive submodule bump breaks the TypeScript compile.Changes
homeassistant-frontendsubmodule to current upstreammaster— brings in the newbrands-url.tsthat returns/api/brands/integration/{domain}/icon.png?token=…, along withfetchAndScheduleBrandsAccessToken/clearBrandsTokenRefreshexports.useFallback: truefrom thebrandsUrl({...})call insrc/dashboards/hacs-dashboard.ts— the field no longer exists onBrandsOptions. Fallback is now the HA backend's job (stale-while-revalidate through the proxy)._brandsAccessTokeninbrands-url.tsis bundle-scoped, so HACS must populate its own copy; upstream'sfetchAndScheduleBrandsAccessTokensilently swallows failures on older HA backends. Clear the refresh interval indisconnectedCallbackto avoid leaking thesetIntervalwhen the panel unmounts.Fixes hacs/integration#5171
Fixes hacs/integration#5223
A companion PR in the integration repo (hacs/integration) updates the HACS Update entity's
entity_pictureto use the same authenticated proxy path.Test plan
script/bootstrap && script/buildcompiles clean (CI via.github/workflows/test.yml).brand/icon.pnginline: downloads table shows real icons; rendered<img>hassrc=/api/brands/integration/{domain}/icon.png?token=….darkOptimized(filename prefixed withdark_).brands/access_tokenWS command): dashboard renders without thrown errors —fetchAndScheduleBrandsAccessTokencatches silently.🤖 Generated with Claude Code