Inspiration

Buying skincare is guessing. A shelf holds four hundred bottles and none of them know your face. Perfect Corp's YouCam API can actually look at skin and score it — so the interesting question is not "what is wrong with my skin", it is "what do I put in the basket on Friday". Skin to Shelf closes that gap: analysis on one end, a real product with a real price on the other.

What it does

You submit a face photo. Perfect Corp's AI Skin Analysis returns 13 scored markers, an AI-derived skin age, and a skin type resolved separately for the whole face, the T-zone and the U-zone. Every detected region comes back painted onto your own photo as a detection map, so a score of 65 for pores is not an abstraction — you see where they are.

The lowest-scoring markers drive a prioritised morning and evening routine. Ingredient conflicts are scheduled around rather than ignored: a retinoid and a BHA never land on the same evening. Each step is then matched to a real, purchasable product at a live price through SerpApi Google Shopping, solved against a budget you choose, so the total is a number you can actually spend. The routine prints as a PDF regimen card, and a re-scan compares the two scans marker by marker — including the ones that got worse.

How I built it

Node and Express on the back, plain ES modules and no bundler on the front, so a reviewer can clone it and run it with npm install && npm start. It also runs with no API keys at all: fixture mode serves recorded responses, so the full experience survives a fresh clone by someone who has neither key.

Challenges I ran into

The published documentation disagrees with the API in three places, and every one of them was only findable by running a real analysis against production.

  1. The task state lives in data.task_status. The documented data.status does not exist, so reading it yields an empty string on every poll — the client spun for 92 seconds and reported a timeout on a task that had finished in eight.
  2. data.results.output is an array whose entries name themselves in a type field, not the concern-keyed object the docs show. Four of the entries are not concerns at all: the overall score, the skin age, three per-region skin-type rows, and the resized source image.
  3. format decides the entire result contract. Omitted, the task hands back a ZIP to download and unpack. With format: "json" the scores arrive inline and every mask comes as a ready-to-render URL.

The fixtures in this repo are shaped against a captured live response, which is committed, rather than against the documentation.

Accomplishments I am proud of

The detection map. It was written off as unrenderable early on, because no live analysis had completed and the recorded masks were dead links. Once live mode worked, the masks turned out to be finished overlays — and showing someone where a marker was detected on their own face is the moment the product stops being a dashboard.

What I learned

Do not trust a response shape you have not seen. Two of the three bugs above were confidently written against the documentation, passed review, and would have failed on the day.

What is next

Per-region routines. The API already tells us the T-zone is normal while the U-zone is dry — that justifies different care on the forehead than on the cheeks, and nothing on the market does it.


The faces in the demo are synthetic, generated by StyleGAN2. They depict no real person, which is what makes it defensible to attach skin scores to a face at all.

Created with AI assistance, curated and quality-checked by a human.

Built With

Share this project:

Updates

Submission history