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.
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.
Test coverage
113 PHPUnit tests
101 run with no network or creds
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.
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.
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.
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 — rides in the carousel as its own card.
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.