Home
[ HERO — desktop · message → playlist result · full-bleed 2880×1400 ]

Send a message you can't say — as a playlist

playmsg turns a message into a playlist whose song titles, read top to bottom, become that message. It then makes the result easy to share. I set the goal, then designed, built, and shipped it solo.

Visit playmsg ↗
Role
Solo project
Product · design · build · deploy
Timeline
Mar 2026 – Present
Concept to launch
Status
Shipped
Live at playmsg.live
Skills
Product thinking
Interaction & visual design
Full-stack (with AI)
Impact

I set the goal, designed it, and shipped it solo. It's a viral-first product: type a message and playmsg matches songs so their titles, read top to bottom, become that message.

Solo
design · build · ship
Live
playmsg.live, in production
0→1
idea to deployed
North Star
shareability (K-factor)
Highlights

Type a message. Get a playlist. Send it.

[ 9:16 — input screen ]
01/ Type your message
[ 9:16 — result screen ]
02/ Playlist on Spotify
[ 9:16 — share & OG card ]
03/ Share the link
[ square image · inspiration → playmsg ]Inspiration behind playmsg
The Idea

A love letter, delivered as a playlist

I blog as a hobby, and one post stuck with me: someone had received a love letter as a playlist. I wanted a tool that made that easy, so I built one.

The Goal

Success means it gets shared

I built this to spread from day one, so I set one north star: shareability, measured as K-factor (how many new users each user brings in). Every decision below flows from it.

K-factor
it compounds
Make
Send
Open
every recipient who opens it can start the loop again
Decisions

Three decisions across matching, layout, and sharing. Each one made to get the playlist sent, not just made.

Decision 01

Make the API the backup, not the engine

The first version called the music API once for every word. A single sentence fired off dozens of calls, hit rate limits, and stalled. The fix was to move matching into a local dictionary and call the API only for the words it couldn't find. The real-time API should fill the gaps, not do the work.

First attempt
Call the API for every word
iAPI call
missAPI call
youAPI call
soAPI call
muchAPI call
429 Too Many Requests
off the API
The fix
Local dictionary first, API and AI for the gaps
i✓ dictionary
miss✓ dictionary
you✓ dictionary
so✓ dictionary
muchAPI / AI
~80% matched, 0 AI
Decision 02

When a tech limit made it more shareable

The message has to read clearly in a screenshot.

Before · album art
[ album art — broken & slow ]
Covers loaded slowly, broke under rate limits
Art pulls the eye off the message
After · title-first
[ title-first — message crystal clear ]
+Nothing competes, so the message reads instantly
+Fast, screenshot-ready

So I dropped album art for a title-first layout. The tech constraint ended up making the result more shareable, not less.

Decision 03

Sharing without a Spotify login

Every extra step before sharing kills virality.

[ mobile — recipient opens a shared link, no account ]
01
Open by default
Playlists encode into shareable URLs, so anyone opens one without a Spotify account. Depending on a streaming-service save would have gated the very thing that spreads.
02
Login only at save
A login is asked only when saving, never to view or share. The path from "made it" to "sent it" stays frictionless.
Execution

Set the goal, designed it, and shipped the whole thing

Product to deploy, built with Claude Code. The real skill was directing the AI: batching decisions, splitting workstreams, and fixing conventions up front.

Core
Next.js 16 React 19 TypeScript Tailwind v4
Services & APIs
Spotify Web API Upstash Redis Spotify OAuth (PKCE) Google Gemini MusicBrainz
Infra & tooling
Claude Code Vercel pnpm Vitest GA4
Next

Built to spread. Now to spread it.

The product is wired for virality: URL sharing, dynamic OG cards, GA and UTM in place. The north star is K-factor, fed by three inputs, each shaped by a decision I made.

01Create rate
visit → made
02Create → share
trust + friction
03Share → visit
the screenshot + the look
[ desktop — 16:10 ]
Learnings

What I'd carry forward

A constraint can become a better design
Dropping album art wasn't a compromise. The limit pushed me toward a cleaner, more on-message layout. Building it myself turned a tech wall into a design choice.
Designing and building as one
Doing the matching, OAuth, and deploy myself meant every design choice got weighed against "can this ship?" Design and feasibility became one decision, not two handoffs.
Set the goal, then design to it
Naming shareability first, then bending every decision toward it, is what kept a for-fun project coherent enough to ship.