Repository navigation
feat(games): game pills show the game's app icon, never a wordmark sliver - #398
Merged
Merged
Conversation
…iver
The 20 px game pills ("Popular here", "Your games") drew the game's
catalogue picture, which for anything that came from Wikidata is the wide
wordmark cropped to a sliver ("AGI GEN", "ROC LEA").
Packs can now carry the game's own square app icon (`appIcon`, a PNG or
WebP beside the pack). It is checked by its bytes on every way in —
upload, community index, catalog feed, bundled snapshot: PNG or WebP,
square, 32-512 px, at most 25 KB — and stored with the pack. It is served
on GET /api/packs/:slug/app-icon (the installed pack's, else the bundled
snapshot's, so popular titles nothing installed runs still have one) and
GET /api/catalog/packs/:slug/app-icon. CS2 ships its own with the module.
Every game summary carries `appIconUrl`.
GameMark now draws, in order: the app icon, the IGDB cover cropped square
from the top, or the initials on a per-game palette tint — never a wide
logo. The picker, profile "Your games", /welcome/games and Home chips use
it; GameThumb (the portrait cover thumb) is gone.
Games saved while search ran on Wikidata kept its wordmark for good once
IGDB was set up. They are now re-resolved against IGDB in the background
(at startup and when IGDB credentials are saved; rate-limited, same slug
or same normalised name only) and gain the IGDB id and cover, keeping
their id and slug.
Bundled packs synced from Auto-Tournament/packs#7 (30 packs at x.y.2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sivert-io
force-pushed
the
feat/game-app-icons
branch
from
September 25, 2026 09:02
3e03674 to
a0e6ffd
Compare
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Depends on Auto-Tournament/packs#7 (the icons and the
appIconfield). The bundled snapshot here is synced from that branch; merge the two together — an instance without this PR refusesappIconin the feed as an unknown field.Problem
The 20 px game pills ("Popular here: League of Legends / Dota 2 / Trackmania", "Your games: Counter-Strike 2 / Rocket League / Valorant") drew the game's catalogue picture. For anything Wikidata supplied that is the wide wordmark, cropped to an unreadable sliver ("AGI GEN", "ROC LEA").
What changes
Packs carry an app icon
appIconin the pack schema: a relative path to a square PNG or WebP (../app-icons/<slug>.webp).checkAppIconchecks the bytes, not the name: PNG or WebP (VP8, VP8L and VP8X headers read), square, 32–512 px, at most 25 KB. Refused, not fixed up, on every way in: upload ({ pack, icon, appIcon: <base64> }), community index, catalog feed, bundled snapshot.game_packs.app_icon(base64) +app_icon_type(the auto-migrator adds the columns).GET /api/packs/:slug/app-icon(public, like the tile: the installed pack's, else the bundled snapshot's, so a popular title nothing installed runs still has one) andGET /api/catalog/packs/:slug/app-icon(admin: installed, snapshot or feed).nosniff, sandbox CSP.scripts/sync-bundled-packs.mjscopiesapp-icons/;api/bundled-packsre-synced (30 packs at x.y.2, soseedBundledPacksupdates installed ones).appIcon: '/games/counter-strike-2-app-icon.webp'(Steam client icon).appIconUrl.Pills
GameMarkdraws, in order: the app icon (object-fit: coveron a square source) → the IGDB cover cropped square from the top → the initials on a stable per-game tint from the palette tokens. Never a wide logo: a cover is only used when it is onimages.igdb.com. Theme radiusradii.sm.GameThumb(portrait cover thumb) removed; the wide onboarding cards keep their logos.IGDB re-resolve (games stored before IGDB was set up keep a Wikidata wordmark for good otherwise)
resolveStoredGamesAgainstIgdb(): rows with no IGDB id andsourcewikidata/builtin, players' picks first, 60 per pass, 350 ms apart. Matches by the same slug or the same normalised name only; takes IGDB id + cover, keeps id and slug. No match →igdb_checked_at, retried after 30 days.Which image each game gets (fresh install, IGDB set)
app-icons/SOURCES.mdin the packs repo.Checks
eslint .: 0 errors. Typecheck ratchet: api 21, client 52 (unchanged).docs:apiregenerated.tests/api/app-icons.spec.ts: valid PNG/WebP (all three WebP header kinds) accepted; oversized, GIF, SVG, non-square, empty refused; path rules; every bundled icon passes; upload → served asimage/webpand named on/api/games/playable; oversized/wrong type refused over HTTP; built-ins carryappIconUrl(null for LoL); IGDB match picking.Game icons are trademarks of their owners and are used only to identify the game.
🤖 Generated with Claude Code