← back to work

PersonalityLive

TrackRecord

Paste a playlist link. Get a personality read. Meet yourself, through your playlist.

The problem

Your playlist knows you better than most people do.

Studies have shown for years that what's in someone's library tracks personality more honestly than most things they'd willingly say out loud — more honest than a dating profile, more revealing than a Myers-Briggs result. The songs people return to, the genres they live in, the artists they defend in arguments, the gap between two tracks they listen to back to back — all of it is data. Deeply personal, highly specific data.

Nobody has built a tool that actually does something interesting with it.

The solution

A personality profile worth sharing.

Paste a public playlist link from Spotify, Apple Music, YouTube Music, or Deezer — or two links, for a couples read. TrackRecord pulls the actual track listing straight from the streaming service — clean titles, no OCR, no hallucinated song names — and reads the person, not the playlist, using the library as the evidence. The deliverable is a carousel of themed cards, built to share — and one of them is a mosaic of your name rendered entirely out of your own album covers — with a magazine-length deep dive underneath for anyone who wants the long version. Every claim is earned by named tracks, transitions, and decades.

No screenshots, no recordings, no uploads of any kind. Just a link.

Anatomy

See how it actually works.

A set of system diagrams traces a pasted link through the platform fetchers, the three-pass model split, and the deterministic verifier layer — the model proposes, code disposes — drawn in one visual language.

Under the hood

What's actually running.

Inside the verifier

An LLM can't be trusted to obey a rule just because the prompt states it — so it isn't asked to. Every read passes through a layer of deterministic verifiers that run in code, not in the model: valid JSON and card-schema structure, no fabricated song titles (the prose may only cite tracks that were actually in the library), no fourth-wall breaks, no banned clinical vocabulary, and — in couples mode — no hallucinated gendered pronouns and no recycled framing clichés. A failed check doesn't ship a weaker answer; it feeds the exact failure back and forces a corrective regeneration. In a 50-read evaluation across the full pipeline, the verifiers caught and self-corrected real slips the prompt alone had let through — a reflexive pronoun, an over-used "famous couple" default, a stock metaphor. The model is creative; the verifier is non-negotiable.

Four streaming-platform fetchers behind one abstraction

A URL parser detects the platform, dispatches to the right fetcher, and returns a normalized song list. Spotify is the interesting one: its Web API stopped returning playlist tracks to Client-Credentials apps in late 2024, so playlists are read from the embed page's serialized JSON instead — the same data, without the OAuth wall — while albums still use the official API. Apple Music is scraped from the public share page (parsing the embedded JSON-LD when present, falling back to Apple's serialized React state for user-created playlists). YouTube Music goes through the YouTube Data API v3, and Deezer through its public API. The AI never knows which platform the data came from.

A carousel of personality cards

The cards are the page hero; the long-form sits below as a collapsible "Deep Dive." Each is themed, with its own accent color, its own share button, and its own deep-link URL: Persona (the 2–4 word title), The Read (the synthesis), The Roast (affectionate ribbing earned by specific musical evidence), The Toast (the warm send-off), Kindred Spirits (historical figures whose character matches yours, each with a one-line reason rooted in the music), Datapoints (the library by the numbers), Contradictions (the two songs furthest apart in the library, and what holding both reveals), By the Numbers (where the library maps onto established personality-research frameworks — presented as patterns the library leans toward, never as scores), and What's Next (songs not yet in the library, chosen to match the patterns already in it). A couples read swaps in a famous-couple match and a set of bridging songs. The carousel's showpiece — the cover-art mosaic — gets its own section below.

The name “Maya” spelled out in album cover art

Your name, built from your covers

The listener's name, rendered as a flowing script masthead (Dancing Script, via FreeType), its letters tiled from their own library's album art — their music, literally spelling their name. It runs as a detached background worker on PHP GD with zero AI tokens — pure image composition, no model call. Each track's cover is resolved through Deezer's public search with a forgiving free-text query (first-artist + cleaned title, to survive the collabs and "(From the Movie)" suffixes that break exact matching), fired in throttled concurrent batches so the lookup isn't dropped for hammering the API. Covers are sorted by luminance — the brightest tiled into the name, the rest dimmed into a full-bleed backdrop — and the letterforms are alpha-composited at pixel resolution so the cursive stays fluid instead of stair-stepping on the tile grid. Because the server's filesystem is read-only, the finished PNG is written to a MySQL MEDIUMBLOB and streamed from its own cache-immutable endpoint. Official editorial playlists (owner "Spotify," "Apple Music") are skipped — there's no personal name to celebrate.

Privacy by architecture

No uploads of any kind — you paste a link, nothing of yours is ever sent to the server. The app fetches your playlist's track list from the streaming service, hands it to the AI, and never stores it. The only persisted artifacts are the generated read and its share images, each tied to a random share URL that nobody can guess. No accounts, no tracking pixels, no retention of your library. The privacy posture is structural, not promised.

Prompt as the product

The runtime prompt runs in three passes on a deliberate model split: a fast analyst (Haiku, personality_pass_1.md) extracts structured, source-anchored observations; a card-writer (Sonnet, pass_2.md) composes the carousel; an essayist (Sonnet, pass_3.md) expands the cards into the long-form deep dive. The writer draws from a five-voice bullpen — five distinct writer personas, each matched to the character of the library, so a metalcore library and a bedroom-pop library never read in the same voice. The frame is explicit: the read is the personality read, the music is the evidence — every general claim earned by named transitions, returning artists, era choices, or lyric moments. Four research frameworks (MUSIC model, Big Five / OCEAN, Empathizer–Systemizer, STOMP) inform the thinking but are never named in the prose — they surface only in "By the Numbers," framed as patterns the library maps onto, never as scores. Clinical vocabulary is banned. Anthropic prompt caching is on the system block, so repeat reads stay fast.

Test coverage

91 / 91 PHPUnit tests ✓
2,083 assertions
PHP 8.4 · PHPUnit 10.5

Markdown parsing across all three passes, card-schema validation, the runtime verifier rules (music-leak, fourth-wall, pronoun, cliché, valid-JSON, structure), and live canary tests against the Spotify, Apple, YouTube, and Deezer fetchers. Beyond unit tests, a 50-read quality evaluation runs the real pipeline — Haiku plus Sonnet, the production model split — across deliberately contrasting libraries, to check voice, specificity, and that the verifiers actually fire.

Instrumented, not flown blind

A read-only admin dashboard tracks usage as it happens: total and per-day reads, the deep-dive open rate (the engagement signal that actually matters), and breakdowns by platform, mode, and which of the five writer voices each library drew — plus the most recent reads and the "did this see you?" feedback. Every query is guarded, so a missing table degrades to a blank instead of taking the page down. The measurement ships with the product, not after it.

Stack

PHP 8.4 · MySQL · PDO
Claude API — three-pass (Haiku + Sonnet), prompt caching
Deterministic verifier layer (propose / verify)
Spotify (embed scrape + Web API) · Apple Music scraper
YouTube Data API v3 · Deezer API (tracks + cover search)
PHP GD + FreeType — server-side cover-art mosaic
Detached async workers (read · deep-dive · mosaic), no cron
DB-stored generated images (read-only filesystem)
html2canvas card image export
PHPUnit 10.5 — 91 tests, 2,083 assertions
No framework · No Composer · No build step

Status

Live, still being shaped.

The app is live. The cover-art mosaic, the Contradictions and What's Next cards, couples mode, and the long-form deep dive all shipped recently; the prompt keeps iterating as reads come back, with each new failure mode answered by a new verifier. Next: a tighter share loop, and smarter handling of very small libraries.