Project 01 · Consumer iOS · 2025–2026

Nobody finished onboarding. Personalization worked anyway.

Sift is a taste-first event app for New York, co-built and shipped to the App Store. We designed an onboarding flow to learn your taste before you saw a single event. Not one user completed it — and the recommender reached full confidence for most of them regardless.

My roleCo-founder — product & engineering
TeamFour co-founders
StackReact Native, Expo, Supabase
StatusLive on the App Store
0 of 41completed the taste-setter
60%reached full confidence (n≈25)
20.5%App Store conversion, 79 views
ScreenshotFeed · 1290 × 2796
01 · Deck
ScreenshotMood picker · 1290 × 2796
02 · Taste-setter
ScreenshotEvent detail · 1290 × 2796
03 · Event
ScreenshotShare-sheet import · 1290 × 2796
04 · Import
Replace with App Store screenshots at 1290 × 2796 (iPhone 15 Pro Max), exported at 2×.
01

The problem

New York has more events on any given night than a person could evaluate in a week, and almost none of them are relevant to any particular person. We ran 20 user interviews before writing product code. Two findings shaped everything after.

The first was fragmentation: 87% of the 18–35 New Yorkers we spoke to used three or more apps to figure out what to do — Eventbrite, TimeOut, Instagram, Resy, a group chat. The second was sharper, and it was a negative result. Zero interview subjects asked for another social feed. People did not want more to browse. They wanted an answer.

“We spend most of our time looking into activities we end up not even going to. We just get overwhelmed and give up.”

Sam, 23 · user interview

“Honestly? I don’t want another social media app. I just want to know what’s good this weekend.”

Recurring theme across 20 interviews

That pushed us away from a feed and toward a ranked deck: one card at a time, ordered by predicted fit. Which creates a cold-start problem. A recommender with no signal cannot rank, so our first instinct was the obvious one — ask the user up front.

02

What I built

The client is React Native on Expo; the backend is Supabase. The interesting parts are the ingest pipeline and the scoring loop.

Six live scrapers pull from Dice, Resident Advisor, Luma, Fever, NYC museums and Eventbrite, refreshed every three days via GitHub Actions. Claude Sonnet finds what the scrapers miss — pop-ups, sample sales, gallery openings. Everything ingested is then cut hard: an LLM rubric rejects tourist traps, corporate spam and kids’ events, which removes roughly 85% of incoming inventory. What survives gets a vibe score from 1–10 via gpt-4o-mini; anything under 5 never loads.

Aggregators need the firehose because their economics depend on total inventory. We don’t, which is the whole design premise: rejection is the product.

DiagramIngest → reject → score → rank
Pipeline
ScreenshotAmplitude funnel
Instrumentation
The ingest and scoring pipeline, and the Amplitude view the funnel below was read from.

On the client, every swipe carries intent. Each gesture updates four independent signals — category, tag, borough, price band — and the deck re-ranks in under 200ms.

GestureIntentSignal effectWeight
RightGoingCategory, each tag, borough+0.15 / +0.08 / +0.06
LeftNot nowNo taste effect; resurfaces in 2–5 days0.00
DownNot interestedCategory penalty; 3 strikes hides permanently−0.05
UpInspectOpens detail, deliberately no signal

Cold start blends quality and timing for roughly the first 20 swipes, then hands over to personalized ranking. That threshold is what confidence measures — an internal diagnostic, built to check the recommender had enough signal before we trusted it. It turned out to be the most important number in the product.

03

What the data said

We launched with no paid acquisition. The App Store funnel was healthy — 157 impressions, 79 product page views, 18 first-time downloads, a 20.5% conversion against Apple’s typical 5–7%. With 23 seeded TestFlight users still active, that put us at 41 people.

Acquisition · App Store, launch to week 3, zero spend
Impressions
157
Product page views
79
First-time downloads
18
20.5% page-view-to-install. Strong ratio, small denominator — 79 views is not a stable estimate, and I'd treat it as directional rather than a benchmark claim.

Then I pulled the onboarding funnel expecting a drop-off curve, and got something that didn’t resolve.

Personalization · all 41 users
Opened the app
41
Started the taste-setter
17
Finished the taste-setter
0
Reached full confidence
~25
Not a low completion rate. Zero, out of 41. And roughly 60% of active users reached full personalization confidence anyway — through swipes, saves and repeat category visits alone.

The mechanism was in our own design and we hadn’t noticed it. Cold start hands over to personalized ranking after about 20 swipes. Twenty swipes takes under two minutes. The taste-setter was asking users to spend ninety seconds declaring preferences the deck would infer from two minutes of ordinary use.

The onboarding flow wasn’t a bottleneck we needed to widen. It was a question the product was already answering by watching.

The finding

This surfaced because two independent sources agreed. A heuristic UX audit flagged the flow as skippable friction; separately, the scoring code showed confidence accumulating for users who had never touched it. Neither alone would have been convincing — the audit could have been my taste, and the score could have been a bug. The finding lives in the agreement between them.

On the numbers

Every figure here comes from a launch cohort of 41 users. The percentages are honest but the denominators are small: 60% is roughly 25 people, and the zero is a genuine zero rather than a rounding artifact. I’d re-run all of it at 1,000 users before treating any of it as settled — but the direction was clear enough to act on, and a design decision that costs every new user ninety seconds does not need p < 0.05 to be worth revisiting.

04

What I'd do next

Cutting the taste-setter is the obvious move and the least interesting one. The more useful question is what else in the product asks for information it could observe instead.

  • Cut the taste-setter entirely; keep one optional neighbourhood prompt at first save, where intent already exists
  • Surface confidence to the user as a reason — you’re seeing this because you saved three like it — turning an internal diagnostic into trust
  • Instrument the inverse: which users never reach confidence, and what they have in common
  • Re-run the audit against the scoring code each quarter, since that pairing is what caught this
BeforeMood picker, screen 1 of 4
Shipped
AfterStraight to the deck
Proposed
AfterReason shown on card
Proposed
The proposed flow drops ninety seconds of first-run friction and spends the space explaining why a card appeared.

The broader lesson I took into later work: instrument the implicit path before you build the explicit one. We built the questionnaire because it was the legible solution, and only discovered it was redundant because we happened to have logged the alternative.