Inspiration

You've used a serum for three weeks. Is it doing anything on your face? Product pages answer with someone else's before and after. The question the hackathon brief names, "standing in front of a mirror deciding whether a product is working", has no honest answer in most shops. I wanted one flow that starts from the shopper's own face and keeps coming back to it.

What it does

Miren answers "is this product working on my face?" in four steps, all on one photo:

  1. Scan. After explicit consent, the photo goes server-side to YouCam AI Skin Analysis v2.1. On the live run in the video, it took 6.5 s from photo to 13 concern scores, mapped on the face. Miren presents it as a cosmetic read, not a diagnosis.
  2. Match. Scores under 75 pick a short routine from a 186-product catalog, one product per step. Every pick explains itself in that scan's own numbers, and ingredient warnings stay visible. Moles and eyelid shape are never requested: no cream treats them, so Miren never shops them.
  3. Preview. Makeup uses YouCam Makeup Virtual Try-On on the same photo (6.5 s render). Skincare uses YouCam Skin Simulation (8.4 s), shown side by side and labelled as an illustrative simulation, never a promised result.
  4. Track. Add to cart (nothing is charged) and start tracking: that scan becomes the product's baseline. Weeks later, scan again. Miren compares only measured raw scores, from the same YouCam model and HD/SD profile, after at least two weeks, and says what a photo cannot prove: the cause.

A header switch separates My scans (live YouCam calls) from Demo data (generated, clearly labelled, no API calls), so judges can explore the whole flow without spending units and never mistake a fixture for a live result.

How I built it

  • Next.js 16 / React 19 / TypeScript / Tailwind 4, deployed on Vercel.
  • YouCam APIs, server-side only: POST /s2s/v2.0/file to register the image, presigned PUT upload, POST /s2s/v2.1/task/skin-analysis with HD or SD actions, polling GET /s2s/v2.1/task/skin-analysis/{task_id}, POST /s2s/v2.0/task/makeup-vto, POST /s2s/v2.0/task/skin-simulation. Optional RSA v1 handshake with fallback to the v2 API-key bearer.
  • Parsing: UI scores are displayed; only measured raw scores enter comparisons. Missing raw scores stay missing instead of being filled in.
  • Matching: catalog concern weights rank products (a heuristic, and the product page says so). Skin Simulation intensities come from the same weights; oiliness is left out because the slider adds shine.
  • Abuse and cost safety: every paid call needs a signed HttpOnly session, a same-origin POST, a Vercel BotID check, and an atomic Upstash Redis quota (per session per hour and per deployment per day). The photo is validated before quota is reserved, and quota is reserved before any paid call. Poll tokens are HMAC-signed and bound to session, action and source, so no one can poll an arbitrary task ID.
  • Privacy: no server photo archive. A thumbnail lives in localStorage and the API-quality source in IndexedDB; one confirmed action deletes both workspaces, photos, routines and the session cookie.
  • Tests: 83 unit tests (parser, matching, comparison rules, live upload/task/poll contracts against simulated YouCam and Redis, quotas, migration) and 51 Playwright browser tests at 320, 390 and 1440 px plus mobile WebKit, with automated accessibility checks. CI runs lint, unit, audit, build and e2e.

Challenges I ran into

  • Real photos fail in real ways. An uncropped stock portrait came back error_src_face_too_small. Miren now maps provider errors to plain messages (422 for a photo problem, 502 for a provider problem) instead of a generic failure.
  • A public demo spends real units. Anyone could mint a session and drain the daily cap before judges arrive. Ordering the checks (session, then decode, then quota, then paid call) and adding BotID closed that.
  • A brand's images disappeared mid-build. One skincare brand's CDN started refusing cross-origin image loads in some regions, so I replaced it with 51 Medik8 products from Medik8's public catalog, with concerns taken from the brand's own tags.
  • Honest comparisons are harder than pretty ones. Two scans are only comparable with the same model, a compatible HD/SD profile, valid dates and measured raw scores. Anything else is left uncompared instead of being shown as a fake trend.

Accomplishments that I'm proud of

  • The whole flow runs live on YouCam: scan, try-on and simulation in the video are real calls on the deployed site.
  • The app never overclaims: cosmetic read not diagnosis, simulation not prediction, trend not causation, and demo data always labelled.
  • Production-grade guardrails on a hackathon timeline: signed sessions, bot checks, atomic quotas, fail-closed routes.

What I learned

The YouCam APIs are strong enough that the hard product problem is not getting a score, it's deciding what a score is allowed to mean. Separating UI scores from raw scores, and HD from SD profiles, made the tracking honest.

What's next for Miren

  • Brand pilot: put the scan and try-on on one brand's product pages, with the re-scan reminder as a retention loop.
  • Apparel and accessory try-on next to makeup, so the "how do I look" decision happens in one place.
  • Reminders for the follow-up scan, built on the per-product baselines the data model already keeps.

Built With

Share this project:

Updates

Submission history