USRSE / USRSE/usrse.github.io

feat(badges): host premium badge artwork in R2

Open
#1,954 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
HTML
Stars
33
Forks
104
Avg merge
12h 3m
Merged PRs (30d)
10

Description

Summary

When premium badges (Lifetime Achievement, named awards, decade-anniversary commemoratives, year-stamped conference attendee marks) need elaborate illustration rather than a geometric glyph, host the artwork in R2 instead of bundling it. Keeps the bundle light and lets new artwork ship without a deploy.

Requirements

  • Add a `badge-artwork` R2 prefix (or a dedicated bucket) alongside the existing `PROFILE_PHOTOS` binding in `wrangler.jsonc`.
  • Convention: artwork keyed by `{tier}/{slug}.svg` (or `.webp` for raster). Public-readable via the bucket's `r2.dev` URL or a `BADGE_ARTWORK_PUBLIC_URL` var, mirroring the photos pattern.
  • Optional `artworkUrl` field on the badge payload — when present, the renderer prefers it over the inline glyph; when absent, falls back to the existing `HexStamp` glyph for that kind.
  • Badge component renders the artwork with the same hex frame + accent ring so the visual system stays cohesive whether artwork is bundled or fetched.
  • Loading state: skeleton hex (matching the accent) while the artwork loads, fallback to inline glyph on fetch error.
  • No artwork required for any badge in Phase 1 or Phase 2 — this is a Phase 3 prerequisite for the named-award badges and a prep step for any future commemoratives.

Context

Current visual system (`HexStamp.tsx`) draws geometric primitives inline as SVG paths. Total weight is a few KB and the inline approach lets us color glyphs via the accent palette using `currentColor`. Moving the existing glyphs to R2 would increase complexity (loading states, network round-trips) without meaningful bundle savings.

R2 is the right call only when artwork is large enough to matter (50–500 KB illustrations), photographic, animated, or year-stamped per-conference. Treat it as an opt-in path for prestige badges, not a wholesale migration.

Implementation Notes

  • `R2Bucket` binding in `packages/api/wrangler.jsonc` follows the `PROFILE_PHOTOS` precedent. Add `BADGE_ARTWORK` and `BADGE_ARTWORK_PUBLIC_URL`.
  • Upload pipeline can mirror the photo URL-import path in `packages/api/src/lib/storage.ts` once admin tooling exists. For now, a one-off bash script to upload commissioned artwork is fine.
  • `BadgeItem` shape gains an optional `artworkUrl: string | null`. The renderer's hex-frame component checks it first, then falls back to the per-kind glyph.
  • Cache headers: long max-age + content-hash in the filename so updates invalidate cleanly.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/api/wrangler.jsonc and compare the existing PROFILE_PHOTOS binding, then read packages/api/src/lib/storage.ts for the photo URL-import pattern. Next inspect HexStamp.tsx and the BadgeItem renderer path. Done means the opt-in artwork URL path, framed loading and error fallback, and R2 configuration are covered without changing existing inline glyph behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, cloud, frontend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.