Skip to content

Epic 45 — Profile Badge System (Beta User, Bounty Hero)

New. Decision (user, 2026-06-16): A badge system on user profiles. First badges: Beta User and Bounty Hero (more than 10 bounties claimed). (The Beta User badge is awarded by the Beta flag — Epic 46.)

✅ SHIPPED 2026-06-18. Backend src/services/badges/index.tsBADGES registry (BETA_USER STATIC / BOUNTY_HERO COMPUTED = strictly >10 HIRED BountyClaim), pure resolveBadges(staticKeys, {hiredBountyClaimCount}) + async badgesForUser. GraphQL Badge { key label icon description } + badges: [Badge!]! on PublicUser / TalentProfile / ProducerProfile (field resolvers in resolvers/social.ts; PublicUser carries internal badgeKeys from toPublicUser so only the computed-count query runs). Root User.badges: [String!]! (raw keys, self/admin) retained. Frontend DS ProfileBadges (phosphor icon + native title tooltip, accent per key, renders null when empty) next to the Verified pin on Talent/Producer profile pages + PostCard/SuggestionCard/TalentCard; apps/app/src/lib/badges.ts localizeBadges (i18n by key via shared instance, badges.* keys in en/pt/es, English API fallback); queries extended (PUBLIC_USER_FIELDS, feed author, talent/producer fragments, POST_QUERY). BE 1414 (+10) / FE app 564 / DS 44 (+5 ProfileBadges) tests green; typecheck + i18n-key lint clean. Note: list surfaces that select badges (followers/following/suggestions/search) now issue one bountyClaim.count per row — acceptable at beta scale; batch later if needed.

Why: User.badges String[] exists ("e.g. EARLY_ADOPTER from CasTars Bounty") but is never rendered, and the only profile chip today is the computed Verified pin (verifiedAtverified). This epic adds a small, extensible badge registry + a display component, with the first two badges.

Architecture: A server-side BADGES registry (key, label, icon, description, kind: STATIC|COMPUTED). Static badges (e.g. BETA_USER) live in User.badges. Computed badges (e.g. BOUNTY_HERO) are derived in a badges field resolver on PublicUser (no storage). Render alongside the existing Verified pin. Decision (user, 2026-06-16): "Bounty Hero" = more than 10 BountyClaim rows with status HIRED (earned/successful claims, not merely submitted).

BE-BADGE-001 — Badge registry + PublicUser.badges resolver

Files:

  • Create: castyou-backend/src/services/badges/index.tsBADGES registry + resolveBadges(user) merging static User.badges with computed ones (BOUNTY_HERO when the user's HIRED BountyClaim count > 10).
  • Edit: castyou-backend/src/graphql/schema/index.ts + src/services/social/index.ts — expose badges: [Badge!]! on PublicUser/profile types (Badge { key, label, icon, description }).

Acceptance criteria: A user with BETA_USER in User.badges and >10 HIRED claims returns both badges; others return none.

FE-BADGE-001 — Badge display component

Files:

  • Create: @castyou/design-system ProfileBadges (icon + tooltip) ([[Design System Rule]]); render on profile pages, profile cards, and feed author chips next to Verified.
  • Edit: i18n en/pt/es for badge labels/descriptions.

Acceptance criteria: Badges render with label/tooltip on profiles + cards in all 3 locales; sourced from the design system.

TEST-BADGE-001 — Badge coverage

Acceptance criteria: Registry resolution (static + computed Bounty Hero threshold) and the display component are tested.