Skip to content

Integrate Genius.com lyrics: restore song discovery and curated lyric associations #207

Description

@holden

Goal

Restore the old app's Genius.com song/lyrics workflow in the current Phoenix app: discover a song, associate it with a word or meaning, show artist and source attribution, and give readers access to its lyrics. Track in-app lyric text explicitly; a metadata card with an outbound link is a useful first milestone, but does not by itself restore full lyric-display parity.

Research: 2026-09-27. Current code inspected at 2d848f7aad45fe409a5e808020b74f4af903636b. Related: #100 (earlier provider research), #85 (culture), #143 (Spotify/Music shelf), #67 (evidence wall), #196 (curation persistence).

What the old app actually implemented

Historical implementation is preserved in 36d3b15 — fixes for lyrics, February 7, 2025. This is verified from source, not a claim that the old integration still runs today.

  • GeniusService: bearer-token GET /search; mapped title, primary artist, source URL, year when present, attribution, and the complete result metadata.
  • Genius search controller: authenticated search with Turbo results.
  • Lyrics controller: select/add to a topic, reuse a lyric by source URL, reject duplicate topic associations, resolve/create an artist, and initially display a loading placeholder.
  • Lyric model and FetchLyricsContentJob: enqueue after creation, then update stored rich-text content asynchronously.
  • Actual lyric text came from Zyte browser HTML extraction, not the Genius API. The parser selected [data-lyrics-container="true"], stripped section labels, and collapsed whitespace. The service retried failures up to three times.

Do not port the Rails model/controller architecture or parser verbatim. The parser discarded line/stanza boundaries, artist resolution used name equality, and the background job had no durable failure state to replace the loading placeholder. The current app already has stronger provider, identity, and failure-handling infrastructure.

Current API and access findings

Official sources fetched and inspected today:

  • Genius API documentation: documents GET /search?q=..., GET /songs/:id, song-related referents, and bearer-token authentication. A client access token supports eligible read-only endpoints without asking each reader to sign into Genius. The documented API does not expose a full lyric-text endpoint; text_format is not a full-lyrics retrieval switch. Do not assume search proves a word occurs in a lyric.
  • Genius terms: currently expressly prohibit scraping/data-extraction methods and restrict reuse of Genius content. The old Zyte implementation is evidence of prior functionality, not evidence of current permission. Confirm the API-specific display, attribution, caching, and retention terms before choosing persistence defaults. In-app full lyrics/excerpts require a documented permitted access and display route.

No authenticated Genius requests were performed during this research. Current result quality, pagination behavior, quotas, missing fields, and token availability remain to be measured. Do not treat guessed quotas or search coverage as established facts.

Earlier #100 parked Genius lyrics. Its broader music recommendations also predate the shipped Spotify integration; use today's code as the architecture baseline rather than repeating its old claim that the Music shelf cannot ship.

Proposed implementation

1. Bounded integration spike

  • Confirm a usable server-side Genius client token; introduce GENIUS_ACCESS_TOKEN through runtime configuration without exposing tokens to clients, logs, fixtures, or persisted request data.
  • Probe search and song detail with a small representative set: love, war, grief, bank, solitude, nepotism, an obscure/no-result word, and known song-title/artist pairs. Record response shape, relevance, latency, pagination, and missing-field behavior in docs/integrations/genius.md with sanitized fixtures.
  • Record the supported lyric-text route separately: permission/licensing, an authorized integration, or an explicitly documented limitation with outbound Genius links. Do not quietly recreate the Zyte scrape or label metadata as full lyric support.
  • Specify minimal retained metadata, expiry/deletion rules, attribution, artwork handling, and an application request budget from the applicable terms and probe evidence.

2. Genius metadata and reader links

  • Implement DevilsDictionary.Discovery.Providers.Genius against the existing Discovery.Provider contract and register it through :discovery_providers configuration.
  • Reuse Discovery.Transport and Req, shared budgets, bounded retries, Retry-After, caching, and status reporting. REST GET is already supported; this does not need a new transport stack.
  • Integrate song cards into the existing :music shelf and DevilsDictionaryWeb.Culture. Include title, artist, canonical Genius URL, stable Genius song ID, and permitted artwork/attribution. Use a clear “Read lyrics on Genius” link.
  • Search/title matches remain query evidence. Apply the existing whole-word title gate for automatic word-page discovery; do not claim thematic relevance, a particular sense, or occurrence in lyric text from a title hit. Curated associations should preserve the selected target and curator's rationale through the current curation model.
  • Reuse provider-native IDs for idempotency. Do not merge artists or songs solely by names/titles, and do not equate a Genius song document with a Spotify recording without supported identity evidence. Preserve separate results when a trustworthy crosswalk is unavailable.
  • Missing credentials disable Genius cleanly. Empty results, authorization failure, throttling, and temporary outages must not break other Music providers or block word-page rendering.

3. Restore curated lyric workflow and resolve text parity

  • Provide authenticated search/select/attach to the intended word or sense using current curation facilities; inspect Curation persistence: versioned panels, ballots and reviewed page compositions #196 before introducing another persistence mechanism. Reject duplicate associations and ensure removing one association does not delete the song from every other target.
  • If authorized text retrieval is available, retrieve it asynchronously with explicit pending/ready/unavailable/failed states and retry behavior. Preserve line breaks and stanza structure, sanitize rendered content, and retain provenance and required attribution. Store only the text and metadata the access agreement permits.
  • If access is unresolved, keep this lyric-text milestone open (or split a linked follow-up with an explicit dependency). Ship the metadata/link milestone with honest wording instead of an indefinite “Loading lyrics” placeholder.
  • Lyric-based usage evidence or excerpts require both actual permitted text and a demonstrated match. Do not open the Music shelf's attestation gate just because a Genius card exists.

Acceptance criteria

  • Spike documents observed API behavior, permitted retention/display, request budget, and the decision on lyric-text access; unverified assumptions are clearly marked.
  • Genius provider conforms to the existing registry/transport contract and renders alongside Spotify in the Music shelf with correct attribution and source links.
  • Automatic discovery distinguishes title/query matches from lyric usage and sense relevance; unrelated substring matches are excluded.
  • Authenticated users can find/select/associate a song with the correct target; repeated selection is idempotent and association removal is scoped correctly.
  • Stable Genius identities are preserved without speculative song/recording/artist merges.
  • Missing configuration, empty results, malformed payloads, 401/403, 429, timeout, and unavailable text produce bounded, truthful states without affecting other providers.
  • Any in-app lyric text has a documented permitted source, preserves formatting, and satisfies attribution, expiry, and deletion requirements; otherwise the limitation remains explicit and tracked.
  • Provider fixtures and LiveView tests cover the above outcomes, including duplicate attachment and failure recovery. No live credentials or copyrighted full-song test dumps are committed.
  • Update integration documentation and run mix precommit for the implementation.

Scope boundaries

No playback, karaoke/timed lyrics, bulk artist-catalog crawling, annotation-writing OAuth flow, or automatic historical database import in the initial implementation. Old record migration can be scoped separately once surviving data and permitted retention are established.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions