Who2see
Point a camera at a festival poster and it tells you which of the 200 names are actually for you.
In use · Scan a poster, get your personal lineup.
- Problem
- Festival posters list hundreds of names. You recognise a handful and miss the rest, including artists you would have loved.
- Role
- Design and build, end to end: the Next.js API, the thin Expo iOS client, the model routing that reads the poster, and App Store Connect.
- Learned
- Pick models on evidence, not feel. The cheaper model ran in shadow behind GPT-4o on live traffic, and the logged overlap and cost set the 150-artist line where GPT-4o takes over.
- Studio
- Channel22
- Role
- Design + build
- Year
- 2026
- Stack
- Next.js · Expo · Gemini + GPT-4o vision · Supabase
- Status
- Live
The problem
Festival posters list hundreds of names. I'd recognise a few and miss the rest, including artists I would have loved. Who2see was one of my first quick projects, built to fix that for myself.

How it works
Take a photo of the poster. The app pulls out every artist name and scores each one from 0 to 100% against your own Spotify or Apple Music listening, not general popularity. Your matches become a playlist, so you know the lineup before you get there.
How it's built
A Next.js app holds all the API routes, and the Expo React Native client is kept thin and calls the same endpoints, so the iOS app doesn't need a second backend. Supabase handles accounts and data, and RevenueCat handles subscriptions.
One account on web and iOS
Who2see is a web app and an iOS app on one account. Scan a poster on your phone at the gates and the lineup is on your laptop that evening. Subscribe in either place and you're subscribed in both. That comes straight from the setup above: one set of API routes, one identity in Supabase, and RevenueCat keeping the subscription in sync. Most festival apps are iOS-only and forget you on any other screen.
Reading the poster
Posters are hard to read: two hundred names in a display font, curved, overlapping the artwork and split across days. Extraction runs on Gemini 2.5 Flash at temperature 0.1 with a JSON response schema, with 2.5 Pro as the fallback if Flash fails. Posters with more than about 150 artists go to GPT-4o instead, because that's where Flash starts to miss names. The output still needs cleaning, so a few rule-based passes fix what prompting can't: re-joining band names the model split on their commas, like Earth, Wind & Fire, and splitting a B2B billing into the two DJs actually playing.
Choosing the model
I picked the cheaper model based on data, not instinct. Gemini ran in shadow behind GPT-4o on live traffic, both given exactly the same prompt, and every extraction logged how much the two artist lists overlapped (the Jaccard score) next to what each call cost. Those logs set the 150-artist threshold. Because Gemini only ran in shadow, users always got GPT-4o's answer and were never part of the test.
How the match score works
The percentage is a ranking, not a model call. Signals from your library are weighted by how much they tell you: a top artist counts more than a saved track, which counts more than a track in one of your playlists, which counts more than a follow, since people keep songs in playlists they've never played. Last.fm similarity adds to that, capped per tier, so it nudges an artist you know a little and lifts one you don't know much further. Without the caps, every unfamiliar artist would score near zero and the app couldn't surface anything new.
Spotify's limits
From May 2025, Spotify limited full API access to registered organisations with around 250,000 monthly users. An independent app stays in development mode, capped at 25 users and cut to five in February 2026. Apple Music has no cap but no ranked top-artists list, so the app trades Spotify's sharper signal for Apple's reach.
The App Store listing
People don't search for Who2see; they search for the festival. So the listing is written for someone who has never heard of the app: the subtitle says what it does rather than repeating the name, and the first screenshot shows a poster going in and a ranked lineup coming out. The keywords are the words people actually use: lineup, who to see, festival poster. I run all of App Store Connect for it: TestFlight builds, phased releases, subscriptions, privacy labels and review replies.
Timing ads to festivals
Interest spikes when a lineup is announced and again the week before the festival, and is close to zero in between. So Apple Search Ads runs campaigns around individual festival names, on while that festival is in the news and paused when it isn't, rather than bidding on generic terms all year. A generic term costs the same in March as in July and converts far worse.