Inspiration

Many people build skincare routines from social media and end up stacking actives: a retinoid, a glycolic toner, a BHA and a benzoyl peroxide gel, sometimes on the same night, and often with no sunscreen on the shelf. When their skin reacts, or doesn't improve, they change three things at once and can't tell what helped.

Most skin-analysis demos stop at a score. We wanted the score to answer a practical question about products the person already owns: which of my products are aimed at what my skin shows, and did the one thing I changed make a visible difference?

What it does

Unstack has six screens.

  • Shelf. Add the products you own: pick from a demo catalogue, paste an ingredient list, or photograph the label. A vision model transcribes the list and you review the text before it is saved.
  • Check. A rule engine reads the shelf and reports:
    • layering conflicts;
    • sun-sensitising actives with no sunscreen on the shelf;
    • actives you are paying for twice;
    • fragrance when redness is a focus;
    • combinations that are not conflicts.

Every finding states how strong the evidence is and links its sources (FDA, DailyMed, AAD and others).

  • Plan. A weekly morning and evening schedule in which conflicting actives never share a session, retinoids stay at night and sunscreen goes in the morning.
  • Scan.
    • You pick the concerns you care about and see the YouCam unit cost before you scan.
    • The YouCam Skin Analysis API returns appearance scores and masks, which Unstack overlays on the photo.
    • Results are mapped to your shelf. You see which products are commonly used for the concerns the scan flagged, and which ones target nothing you care about.
    • An optional Fitzpatrick sun profile raises the priority of the sunscreen finding.
  • Experiments. Change one product, rescan every two weeks and see per-concern trends against your baseline. Changes inside a noise band measured from your own baseline scans count as no change. Unstack warns you when something else on the shelf changed during the experiment.
  • Privacy. A diagram of where the photo goes, a live unit ledger, consent withdrawal, and a button that deletes everything on the device.

Unstack makes no medical claims:

  • scores are "appearance scores";
  • guidance is cosmetic;
  • prescription products get "follow your prescriber";
  • the Fitzpatrick type is never presented as a diagnosis.

How we built it

Stack:

  • TypeScript throughout.
  • A React 19 + Vite front end.
  • A small Node http server with no framework.
  • Shared, unit-tested domain logic for ingredients, rules, schedule, concern mapping, experiment statistics and pricing.

The server holds the YouCam key and runs the scan pipeline. User data stays in the browser (localStorage and IndexedDB).

YouCam APIs and why each is used:

  • POST /s2s/v2.0/file and the presigned PUT. These upload the user's photo straight from server memory, so the photo is never written to disk.
  • POST /s2s/v2.1/task/skin-analysis. This is the scan.
    • We request JSON with raw masks (enable_mask_overlay: false) and draw our own overlays.
    • SD or HD is chosen from the photo size.
    • The user picks the concerns, and the price follows from how many they pick.
  • GET /s2s/v2.1/task/skin-analysis/{task_id}. Polling with back-off. The Scan screen shows each pipeline step live, with the API call it makes.
  • POST /s2s/v2.0/task/delete. Called after every task, once the results are copied. We checked live that the result URLs return 404 immediately afterwards.
  • POST /s2s/v2.0/task/fitzpatrick-scale-analyzer. The optional sun profile. It is JPEG only, so the browser re-encodes PNGs first.
  • GET /s2s/v1.0/client/credit. A free balance check before each paid task.
  • GET /s2s/v2.0/credit/feature-cost. A free live price sync. A live price can raise the documented price but never lower it, and the result is quoted before every scan.
  • YouCam JS Camera Kit (integrated, not yet tested on a real webcam). An optional camera guide for experiment check-ins, meant to keep distance, pose and lighting consistent between scans. It loads only after consent and only when the user picks the camera. We have not yet run it with a real webcam, so it is not shown in the demo video.

Spending safeguards:

  • A server-side unit ledger with a hard cap: units are reserved before any paid call, charged on success, released on failure, and counted as spent if the outcome is unknown.
  • Rate limits matching YouCam's documented limits.
  • A per-hour cap on paid tasks.

Testing without burning units:

  • First we ran a 26-unit live verification of the protocol. Its redacted recordings back a mock client that enforces the same rules the live API did: no mixing of SD and HD actions, matching upload length, and 404 after delete.
  • One more 9-unit run then checked the whole pipeline end to end through our own server.
  • 106 automated tests cover the server and the domain logic.
  • The scan and sun profile in the demo video are one live take (26 units). The experiment history shown in the video is demo data.

Label reader: a vision LLM (openbmb/MiniCPM-V-4_5 on Nebius Token Factory) with a USD spend ledger and a hard cap.

Challenges we ran into

  • Units cost real money and are charged only on success. We designed the ledger so that a crash, a timeout or a lost response can never let the server spend past its cap.
  • Result URLs are short-lived. They expire after two hours and return 404 once the task is deleted, so the pipeline has to copy every mask before it deletes. We also found that the masks are served as binary/octet-stream, so the server labels them by their bytes.
  • Fitzpatrick accepts JPEG only. One of YouCam's own sample faces is a PNG, so the browser re-encodes it before upload.
  • A local server that holds a paid key must not be callable from other websites. It accepts only loopback Host headers and same-origin JSON requests, which blocks DNS rebinding and cross-site requests.
  • Scan-to-scan noise. Two scans of the same face never match exactly, so experiments use a noise band measured from your own two baseline scans instead of treating every point of change as real.
  • Saying useful things without medical claims. Every rule has a source and an evidence label, and concerns with weak topical evidence say so.

Accomplishments that we're proud of

  • Seven YouCam endpoints, each used for a reason the user can see, plus a Camera Kit integration that is still untested on a real camera.
  • Privacy by default: a consent gate, the photo held only in memory, task/delete after every scan, and no accounts. The server stores only a unit ledger and anonymous consent receipts.
  • A cheap, honest verification. The full protocol check plus an end-to-end run cost 35 units, and the app shows the unit price before every scan.
  • A demo mode built from real recorded responses, so anyone can try the whole flow without a key.

What we learned

  • Price tiers. YouCam's skin-analysis price depends on SD versus HD and on how many concerns you request (SD 1–4 concerns is 9 units). Letting users choose concerns turns the price into something they can control.
  • Latency and delete. A skin-analysis task finished in about 6 to 14 seconds in our live runs, and task/delete really does remove the result files, which makes "delete after every scan" a meaningful privacy promise.
  • Live prices. feature-cost is the source of truth, and a documented price table can drift from it.
  • What to keep out of the model. Keeping the LLM to one narrow, reviewable job (transcribing labels) made the rest of the app deterministic and testable.

What's next for Unstack

  • More ingredient rules and sources, reviewed by a cosmetic chemist.
  • Barcode lookup for faster shelf entry.
  • Check-in reminders for experiments, and an exportable experiment summary that stays on the device.
  • Hosting with webhooks instead of polling.
  • Localisation.

AI assistance disclosure

  • Building it. Unstack was built with heavy use of AI coding agents (Anthropic's Claude, through Claude Code). Under the entrant's direction, they wrote most of the code, tests and documentation, and ran the browser click-throughs that produced the screenshots.
  • Inside the app. A vision LLM (MiniCPM-V 4.5 on Nebius Token Factory) only transcribes ingredient lists from label photos, and the user reviews the text before it is saved. All findings, schedules, concern mapping and experiment verdicts come from deterministic code.
  • Images. The sample faces are Perfect Corp. images loaded from YouCam's CDN; they are hotlinked, not copied into the repo. No image in the project is AI-generated.

Built With

Share this project:

Updates

Submission history