Skip to content

perf(coins): load resized coin logo variants for badges and icons - #14712

Merged
dylanjeffers merged 1 commit into
mainfrom
perf/fan-club-badge-logos
Oct 26, 2026
Merged

dylanjeffers merged 1 commit into
mainfrom
perf/fan-club-badge-logos

Conversation

@dylanjeffers

Copy link
Copy Markdown
Contributor

Problem

Coin badges are drawn at 14–24px, but they load the coin's full logo_uri. On signed-out /trending (Lighthouse mobile, 2026-10-26) three badge PNGs were 462 KB, 101 KB and 40 KB, about 600 KB of the page's 823 KB of images.

It's not just those three. All 57 coin logos on prod:

total avg largest
original (logo_uri today) 28.5 MB 500 KB 2.2 MB ($STEEL, 1000×1000 PNG)
150x150.jpg variant (est.) 260 KB 4.6 KB 7.4 KB

Where the logos come from

  • artist_coins.logo_uri is whatever the launchpad relay uploaded: the Metaplex token image on Irys/Arweave (gateway.irys.xyz/<id>, which 302s to *.mainnet-1.datasprite-cdn.com). 56 of 57 prod coins point there; $AUDIO is a static asset on audius.co.
  • Irys/datasprite has no resize parameter, and audius.co has no Cloudflare image resizing (/cdn-cgi/image/ 404s). The API returns logo_uri as stored, with no sized variants.
  • Validator node storage (mediorum) does resize on demand. GET /content/<cid>/150x150.jpg resizes any stored image, from the original CID too, not just upload IDs. Checked on prod: a 45 KB original came back as 5.7 KB from both creatornode.audius.co and a third-party node.
  • The Irys → Audius coin migration is already moving logos there:

What this PR does

Adds getCoinLogoUrl(logoUri, displaySize) in @audius/common/utils. For a bare validator node URL (…/content/<cid>) it returns the smallest square variant that is sharp at 3× for that display size: 150x150.jpg up to 50px, then 480x480.jpg, then 1000x1000.jpg. Every other URL is returned unchanged: Irys, static assets, and URLs that already name a variant.

Used where coin logos are drawn small:

  • web: UserBadges (the trending offender), FanClubHoverCard, FanClubTextPostNotification, PriceAndAudienceField, CoinSuccessModal, FanClubInfoSection header, and TokenIcon (covers ~15 more call sites)
  • mobile: TokenIcon (covers UserBadges and the rest), DetailsTileHasAccess

loading="lazy" / decoding="async" are already set inside harmony's Artwork, so nothing to add there.

Today this is a no-op on prod, because no prod logo is on a validator node yet. It starts saving bytes for each coin as soon as its logo_uri moves over, with no further client release:

  1. run migrate-logos-to-audius.ts --apply for existing coins → /trending badge bytes go from ~600 KB to ~15 KB
  2. merge/roll feat(solana-relay): host launched coin images and metadata on Audius pedalboard#90 → new coins are covered from launch

No new infrastructure. It only uses the resizer every validator node already runs.

Safety

  • Mediorum variants are always JPEG, so transparency would turn black. I checked all 57 current prod logos: all are fully opaque (RGB/L, no alpha), so there's no visual change. New launchpad uploads are worth keeping opaque, or the relay could flatten them.
  • The variant comes from the same host as logo_uri, so reachability doesn't change. If the host is down, the original would fail too.

Before / after

On prod /trending, this PR alone changes nothing yet. Every logo there is still on Irys, and the helper leaves those URLs alone. Today's trending page only had $YAK (4.8 KB) in view. The audit's 462 KB / 101 KB / 40 KB logos are typical of the set, and the bytes drop once logo_uris are re-hosted.

Measured in a local web build against prod at DPR 2, signed in. A temporary, uncommitted shim pointed one artist's badge logo_uri at an image already stored on validator nodes:

badge on /trending (14px CSS, 4 on page) URL requested natural size bytes
helper bypassed …/content/<cid>/original.jpg 400×400 45,785
this PR …/content/<cid>/150x150.jpg 150×150 5,708

150px is about 5× what a 14–24px badge needs at 2× and covers 3× up to 50px.

What the audit's /trending logos would cost after the re-host, estimated by resizing the actual files the way mediorum does (150px fill, JPEG q75):

today (Irys original) after re-host + this PR
audit's 3 badge logos ~603 KB ~15 KB
largest logo ($STEEL) 2,212 KB 5.3 KB
all 57 coins 28.5 MB 260 KB

Not in this PR (API / backend follow-ups)

  • Run the re-host script (above). This is what actually moves the /trending number.
  • Optionally, have the API return sized variants the way it does for profile_picture ({150x150, 480x480, 1000x1000, mirrors}), so clients can fail over to mirrors instead of relying on one host. Not needed for the bytes win.

Test plan

  • getCoinLogoUrl unit tests (variant thresholds, trailing slash, non-resizable URLs, empty values)
  • eslint on changed files in web / mobile / common
  • Web dev build against prod, with logos temporarily pointed at a validator node image: badges request …/150x150.jpg and stay sharp at 2×. Irys logos unchanged.
  • Mobile: one-line change to TokenIcon's source.uri. Not run on device.

🤖 Generated with Claude Code

Coin badges are drawn at 14-24px but load the full logo_uri, which
averages 500 KB (up to 2.2 MB) across prod coins. Add getCoinLogoUrl,
which rewrites validator node logo URLs (/content/<cid>) to the
smallest square variant that is sharp at 3x for the display size. Other
URLs (Irys, static assets) pass through unchanged.

Prod logos are all on Irys today, so this takes effect as logo_uri
moves to validator nodes via the Irys -> Audius migration
(pedalboard#90 for new coins, migrate-logos-to-audius for existing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 26, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3b7d3ea

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@dylanjeffers
dylanjeffers merged commit c3c872f into main Oct 26, 2026
18 checks passed
@dylanjeffers
dylanjeffers deleted the perf/fan-club-badge-logos branch October 26, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant