Inspiration

What it does# Purely — Find What's Healthy

Inspiration

We were tired of squinting at ingredient labels in grocery aisles, trying to decode whether "natural flavors" was hiding something we shouldn't be eating, or whether the bottled water we'd been drinking for years actually had PFAS in it. The wellness industry sells confusion as a product — every label looks healthy, every brand claims "clean," and the regulatory truth is buried in PDFs nobody reads.

We wanted to build the app we wished existed: point your camera at anything — food, water, supplements, cosmetics, cleaning supplies, baby food, even clothing — and get an honest, evidence-backed answer about what's actually in it. Not just "good" or "bad," but how bad, by what regulatory standard, and by how many multiples it exceeds the safe limit.

What it does

Purely is a consumer health scanner that turns your phone's camera into a toxin-detection tool. Point it at any product label and it gives you back:

  • A 0–100 health score with a clear rating (excellent / good / okay / poor)
  • Ingredient-level analysis — every component flagged as beneficial, harmful, or neutral
  • Regulatory context that nobody else gives you: legal_limit, health_guideline, and exceeds_by_multiplier (e.g. "40× California's health guideline")
  • Specialized metrics per product type — PFAS detection for water, microplastic risk for packaged goods, paraben/phthalate flags for personal care, seed-oil ratios for snacks, recyclability for packaging
  • A global cache — when one user scans a Coca-Cola, every future user benefits from that analysis instantly

The app handles ~30 product categories out of the box, ships on iOS + Android, and works without requiring a login — your scan history follows your device, not your email.

How we built it

  • Expo SDK 54 + React Native 0.81 + React 19 with the New Architecture turned on, TypeScript strict mode end-to-end
  • expo-router for file-based navigation across Welcome → Onboarding → Tabs (Search / Scan / Top Rated) → detail screens
  • 3-pass OpenAI vision pipeline (ai/analyzeProductImage.ts) — gpt-4o-mini fast pass at 20s, gpt-4o-mini emergency pass at 26s, then gpt-4o fallback at 42s. Images are pre-resized to 448–512px and compressed to 55–65% to stay under gpt-4o's low-detail token threshold. Cost-tuned to the cent.
  • Supabase Postgres for scan history, user profiles, content catalog, benchmark profiles, and a global product-analysis cache shared across all users
  • AsyncStorage as source of truth, Supabase as best-effort mirror — the app keeps working offline; remote sync never blocks the user
  • Anonymous device-ID identity model — every user is a device_${timestamp}_${random} row in user_profiles, race-condition-aware against PostgreSQL 23505 collisions
  • Superwall for iOS paywalls, identity-synced to the same Supabase profile ID so A/B tests and subscription state line up with analytics
  • Mixpanel + AppsFlyer unified through a single trackEvent pipeline with strict event shapes (screen_name, action, element_name, result)
  • Native-thread animations via react-native-worklets and Animated.spring with useNativeDriver: true — 60fps scanline, drawer gestures, no JS-bridge jank
  • EAS Build for CI/CD to TestFlight and Google Play Internal Testing
  • 18 SQL migrations covering onboarding, scan history, storage buckets, subscriptions, referrals, likes, content catalog, benchmark profiles, and the global analysis cache

Challenges we ran into

  • OpenAI cost vs. UX latency was a knife's-edge balance. Too short a timeout and we'd bleed into the gpt-4o fallback ($2.50 in / $10.00 out per 1M tokens vs. gpt-4o-mini at $0.15 / $0.60). Too long and the user thinks the app is broken. The 20s / 26s / 42s tiering took dozens of iterations to land.
  • Cold-start tax — the first scan after app launch adds ~12s for OpenAI's cold start, which had to be designed for, not engineered around.
  • Image compression vs. label readability — pushing images below the 512px low-detail threshold saves ~85 tokens per request, but compress too hard and the model misreads ingredient text. We tuned to 55–65% quality at 448–512px.
  • Anonymous identity at scale — handling concurrent installs racing for the same generated device ID required defensive 23505 unique-constraint handling everywhere a profile gets created.
  • ai/analyzeProductImage.ts grew to 3,402 lines — every timeout, prompt order, model selection, and retry path is interdependent. Refactoring it casually breaks the cost model.
  • Web is intentionally unsupported — Superwall, AppsFlyer, and CameraView are all native-only modules, so we made a deliberate call to ship native-only rather than litter the codebase with Platform.OS guards.
  • Per-category metric extensibility — water needs PFAS, snacks need seed oils, personal care needs parabens. We built type_metrics as a per-ProductTypeKey keyed structure so adding a category never breaks an existing one.

Accomplishments that we're proud of

  • Regulatory-grade honesty — the legal_limit / health_guideline / exceeds_by_multiplier fields are the product's differentiator. No other consumer scanner tells you "this product exceeds the California health guideline by 40×."
  • Anonymous-first architecture — no login wall, no email harvesting, no friction. You open the app and scan. The device-ID model handles paywalls, analytics, scan history, and subscriptions without ever asking who you are.
  • Global cache economics — because we cache analyses by product identity (not by user), every scan amortizes across the entire user base. This is what makes gpt-4o-mini pricing viable at scale.
  • 30 product categories from one scanner — most competitors do food or water or cosmetics. Purely does food, water, supplements, personal care, clothing, cleaning supplies, baby food, pet food, cosmetics, medicine, and more — from the same camera button.
  • Offline resilience — kill the network mid-scan and the app degrades gracefully. AsyncStorage is the contract.
  • Shipped to both stores — version 1.1.1, iOS build 24, Android versionCode 2, live on TestFlight and Play Internal.

What we learned

  • Cost-conscious AI architecture is a design discipline, not an optimization pass. Every prompt, image size, timeout, and model tier has a dollar value. Build the cost model into the code from day one (logTokenUsage on every call) or you'll never recover.
  • Local-first beats cloud-first for consumer mobile. Users don't care that your Postgres is up — they care that the app opens. AsyncStorage as truth + Supabase as mirror is a pattern we'd reach for again.
  • Anonymous identity is a feature, not a limitation. Removing the login screen removed an entire class of drop-off, support tickets, and GDPR overhead.
  • Per-category extensibility wins long-term. The ProductTypeKey union + per-type type_metrics schema means adding "candles" or "vitamins" tomorrow is a prompt change and a benchmark seed, not a refactor.
  • Tuned code is allowed to be ugly. A 3,402-line orchestrator that bleeds money if you split it wrong is correct. Resist the refactor instinct when the seams are load-bearing.
  • Brand voice and product surface can diverge from product depth. The Welcome screen says "Your journey to better skin starts here" — but the engine handles 30 categories. Both are true. Marketing entry points and engineering reach don't have to match.

What's next for Purely

  • Expand the benchmark library — pre-computed scores for the top 1,000 products in each category so the most common scans return in milliseconds without hitting OpenAI at all
  • Lab-evidence-backed contaminant claims — every PFAS / microplastic / heavy-metal flag tied to a specific lab report URL, not just an AI inference
  • Personalized health profiles — opt-in dietary restrictions, allergies, and health goals that re-score the same product differently per user (still anonymous, still device-ID-keyed)
  • Family / household sharing — scan history that follows a household across devices without requiring real auth
  • Web companion for browsing Top Rated and category leaderboards (read-only, no scanner — keeps the native-only camera path clean)
  • Localization beyond US regulatory frameworks — EU REACH, Canadian CCCR, Australian APVMA limits surfaced alongside California Prop 65
  • Apple Health + Google Fit integration so flagged ingredients can correlate with logged symptoms over time
  • Real auth as an opt-in upgrade, not a wall — the device-ID model stays the default forever

How we built it

Challenges we ran into

Accomplishments that we're proud of

What we learned

What's next for Purely

Built With

Share this project:

Updates