Skip to content

feat: show band link icons on the public roster page#609

Merged
BreakableHoodie merged 2 commits into
mainfrom
feat/roster-link-icons
Jul 17, 2026
Merged

feat: show band link icons on the public roster page#609
BreakableHoodie merged 2 commits into
mainfrom
feat/roster-link-icons

Conversation

@BreakableHoodie

Copy link
Copy Markdown
Owner

Summary

Fans had to open each band's profile page just to reach their links. Each /artists roster card now carries a compact icon row of the band's links — capped at 4, in "hear the band first" priority (Bandcamp → Spotify → Instagram → website → YouTube → Facebook → Apple Music → Linktree) — with the full colour-treatment link set remaining on the profile page. Cards without links look exactly as before.

Closes #607

Visuals (local wrangler + seeded D1, both themes): verified in midnight-ember and daybreak — monochrome ghost icons, 40px tap targets, long names truncate cleanly against a 4-icon cluster. Screenshots shared with Dre in-session for the "looks good and practical" gate; auto-merge deliberately not armed pending his visual sign-off.

What changed

File Change
functions/api/artists.js social added to the payload, sanitized server-side via safeReflectSocialLinks (same convention as the other public band endpoints: values normalized to real http(s) URLs / Instagram handle or null; malformed JSON → {}; absent column → null); raw social_links never exposed
frontend/src/pages/ArtistsPage.jsx ArtistCard restructured: outer div + content <Link> + sibling icon cluster (no nested anchors); module-level SOCIAL_LINK_DESCRIPTORS priority list; safeExternalHref/safeInstagramHref re-sanitize client-side; trackSocialClick on click (same link_type keys as the profile page, allowlisted in /api/metrics); theme tokens only
frontend/src/pages/__tests__/ArtistsPage.test.jsx Icon hrefs + aria-labels, 4-cap with priority order, no cluster when social null, javascript: URLs dropped
functions/api/__tests__/artists.test.js Round-trip, malformed → {}, absent → null, server-side javascript: nulling, raw column never exposed
docs/api-spec.yaml social documented to match actual behaviour

Security / correctness notes

Double-layer URL sanitization: server (safeReflectSocialLinks — nulls non-http(s) schemes, normalizes URLs) and client (safeExternalHref/safeInstagramHref gate every href; '#' results are filtered out). External anchors carry rel="noopener noreferrer". Public read-only endpoint; no auth surface.

Verification

  • Tests: backend 743 pass | 6 todo (74 files) incl. 8/8 artists; frontend 517 pass (50 files) incl. 6/6 ArtistsPage
  • ESLint: 0 errors both stacks
  • Format check: clean both stacks
  • Build: green (npm run build --prefix frontend)
  • validate:openapi: 71 documented + 1 internal = 72 route files, no drift
  • Manual smoke: local wrangler pages dev + seeded D1 — icon caps/priority, sanitized API payload, both dark and light themes screenshotted; reviewed by Vera (code) + silent-failure pass (Theo)

Built by Sonny · Reviewed by Vera & Theo · 🤖 Claude Code

Fans had to open each band's profile page just to reach their links.
Each /artists card now carries up to 4 monochrome icon links in
hear-first priority (bandcamp, spotify, instagram, website, then
youtube/facebook/apple_music/linktree), with real 40px tap targets.
The card is restructured (outer div + content Link + sibling icon
cluster) so profile navigation and external links never nest anchors.

/api/artists now returns `social`, sanitized server-side via
safeReflectSocialLinks like the other public band endpoints; the
frontend re-sanitizes with safeExternalHref/safeInstagramHref as a
second layer. Clicks feed the existing social_link_click metric.

Closes #607

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@BreakableHoodie BreakableHoodie added enhancement New feature or request priority:p2 Medium priority labels Jul 17, 2026
Copilot AI review requested due to automatic review settings July 17, 2026 00:13
@BreakableHoodie BreakableHoodie added enhancement New feature or request priority:p2 Medium priority labels Jul 17, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

The unsafe-scheme sanitization test needs a literal javascript: URL;
document the eslint-disable the same way validation.test.js does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 17, 2026 00:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@BreakableHoodie
BreakableHoodie merged commit 46cb7eb into main Jul 17, 2026
22 checks passed
@BreakableHoodie
BreakableHoodie deleted the feat/roster-link-icons branch July 17, 2026 00:21
@BreakableHoodie

Copy link
Copy Markdown
Owner Author

Layout v2 pushed per Dre's feedback: the icon cluster moved below the name/meta block — a long band name now renders in full and the card grows vertically instead of truncating ("The Time Travelling Garbage Collectors" seeded as the worst case renders cleanly in both themes). No-link cards keep their original height. All gates green: frontend 518 tests, lint/format/build clean. Auto-merge still held for Dre's visual sign-off.

@BreakableHoodie

Copy link
Copy Markdown
Owner Author

Correction to my previous comment: this PR had already been merged when the v2 layout was ready, so the truncation fix ships as follow-up PR #612 (icons below the text row — screenshots with Dre).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority:p2 Medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(roster): show band link icons directly on the public roster page

2 participants