Inspiration
A bottle can promise clearer skin in seven days. The person holding it has no way to check. They look in a different bathroom light, after a short night, with a hand that has been on their face all evening, and they decide the serum failed. Or one flattering photo convinces them it worked, and they repurchase. Either way the decision is a mood, not a measurement.
Beauty shopping makes this worse. The shade, the claim, and the checkout all happen before anyone has lived with the product long enough to know. The industry sells the before-and-after. Nobody sells the wait.
WorthIt started as a refusal. A personal test should say a product is working only when the change clears the noise of your own face, your own camera, and your own week. Every other morning the honest sentence is "too early." It is not medical care. It never calls itself a clinical trial. The flex is that it would rather lose a sale than lie.
What it does
WorthIt is a three-device trial that starts when you buy something and does not let you grade it early.
The phone is the instrument. YouCam Skin Analysis scores acne, pores, redness, and texture from a Camera Kit capture that will not take the photo until the light and the angle pass. Five scans, back to back, same light, are not five days. They are the noise floor of the instrument. One scan each morning is a day. WorthIt stores YouCam's raw score. The kinder ui_score is what beauty apps show you so you feel good. We do not judge a product on a number that was adjusted to be nice.
The watch is the week the mirror cannot see. A Galaxy Watch4 has no camera and, on the model we built for, no skin-temperature sensor, so we did not invent one. It feels the wrist. After a short calibration, accelerometer and gyroscope decide whether a motion was a face touch or one of the other things a wrist does. A touch buzzes and lands on the laptop while you are still in the room. It also catches the wake, carries the trial day on a tile, and lets you say the product out loud. Sarvam turns that clip into a product, an ingredient, and the day you started, then speaks the confirmation back. "I started the salicylic acid cleanser today" becomes a trial, not a note you forget to type.
The phone app is the night. Health Connect reads the sleep the watch already recorded. A cycle phase is sent only when today actually falls inside a period record. Other phases are not guessed. Humidity comes from the place you set. Adherence is a check-off, not an assumption.
The laptop is the ledger. Every morning is one row:
$$y = \text{intercept} + \beta \cdot (\text{on} \times \text{adherence}) + \text{covariates} + \text{noise}$$
Covariates enter only when they vary: sleep debt, face touches, humidity, cycle, and heart-rate variability when a real signal exists. A flat column is dropped. It is not allowed to pretend it explained the day. Instrument noise is separate from the day-to-day spread:
$$\mathrm{MDC}_{95} = 1.96 \cdot \sqrt{2} \cdot \mathrm{SEM}$$
The product coefficient has a Normal-Inverse-Gamma posterior. WorthIt says working only when (P(\beta > \mathrm{MDC}_{95}) \ge 0.95). Inside the band, the verdict is no detectable effect. A drop that lines up with the days you used it is moving the wrong way, which is a different sentence from "nothing happened." Everything else is too early, and a seeded Monte Carlo on your own noise names the earliest day an honest answer could appear. Eighty percent of simulated trials have to clear the bar. The effect size is the brand's measured claim when one exists, otherwise ten percent of your baseline. As real mornings arrive, the day-to-day prior updates, and that date can move earlier. The screen says so: was day 19, now day 16.
The same bar is applied before you buy the next bottle. Photograph the pack, or scan a barcode Open Beauty Facts actually lists. Skin Simulation renders the claim on your face. Skin Analysis measures the render. If the change is smaller than your noise, the answer is skip, even if the advertisement is true. If it is larger, the answer is test it, which is not "it works." A block list kills cure, treat, diagnose, guaranteed, and clinical trial before a sentence can reach the screen.
Then the shop, because the decision does not end at the serum. WorthIt reads facial color in CIELAB and ranks foundation, concealer, and lip color by distance to your skin or your lip, not by a bestseller list. Makeup virtual try-on puts one shade, or the whole basket, on your photo. A breakout morning gets a concealer matched to that tone and labeled as a shade, not a treatment. The bag is real retail math: SKUs, quantity, ₹79 shipping, free past ₹999, an order number, and no fake payment. "Bought it? Test it" opens the protocol with that product already filled in. The purchase is the start of the trial, not the end of the demo.
One-side testing is the design we want for a leave-on active, because sleep and weather hit both cheeks and fall out of a left-minus-right difference. WorthIt will only call that split live when a YouCam mask and a face midline actually divide the photo. Until then the one-side advantage stays on screen as a simulation, with the label still on it.
How we built it
One Next.js desk is the source of truth. The browser, the watch, and the phone all write to the account that is using it. There is no pairing code to lose in a demo. Scans, nights, events, trials, the bag, and orders live in a local ledger, with an optional Supabase copy and a delete-my-data path that clears both.
YouCam is called as a lab instrument, server-side, key never in the browser:
- Skin Analysis on every scan, and again on every claim render
- Skin Simulation to paint the claim before we believe it
- Facial Color Tones to rank a shade
- Makeup virtual try-on for concealer, foundation, lip, and blush, one product or a whole basket
- Camera Kit in skincare and HD skincare, strict quality, so a bad photo is refused before it can move a score
- The File API under all of it
Every successful result is cached on the image bytes and the request, not on a one-time file id. Repeating a demo does not burn the unit budget.
The verdict math does not call a language model. Anthropic, when a key is present, only phrases a sentence that the block list has already approved. The number is a conjugate regression and a Monte Carlo. The tests inject an effect and demand "working," feed pure noise and demand a false-working rate at or under five percent, and hand the product a drop that belongs to sleep. If the serum gets the credit, the test fails.
The watch is Wear OS, built for a Watch4. Four swipeable pages, a tile, a wake listener with a 07:30 alarm behind it, and a foreground sensor service. The phone app is the same desk in a WebView, plus Health Connect, a real camera, and a path home over Wi-Fi or USB. Voice on the wrist is a small state machine: product, ingredient, start day. Sarvam transcribes and speaks. The parser, not the model, decides what was said.
Challenges we ran into
The easiest way to look advanced was to lie about a sensor. We kept almost doing it. The Watch4 we had does not measure skin temperature, so a "skin temp versus redness" chart would have been fiction. Beat-to-beat intervals need Samsung's Health Sensor SDK, which is not a normal Maven dependency, so an RMSSD we computed from a heart-rate average would have been a costume. Sleep still comes from the phone. The missing number is left missing.
A face touch was the next trap. The watch cannot see a cheek. A raised arm is not a touch. We record the wrist signature of a real touch against drinking, typing, and a plain raise, then count a motion only when it is clearly closer to the touch than to the other class, and only while the wrist is actually moving. A hold does not keep counting. A second touch inside a few seconds does not count twice. Lab is a confusion matrix, not a vibe. Until that test is run on a wrist, the count is labeled as a wrist guess.
Statistics tried to fool us too. If every day is already "on the product," the effect is not identifiable. We refuse that model. The noise-floor mean becomes the before, so a before and an after exist. A covariate that never moves is dropped instead of being given a story. The earliest honest day is recomputed when your mornings get quieter, and we show both dates rather than locking a flattering one.
YouCam will happily score the same photo twice and charge you twice. Claim copy will happily sound like a clinic. The cache and the block list are there so the demo stays cheap and the language stays inside a personal test. ui_score versus raw_score was its own argument: the API documents that the UI score is adjusted because people prefer good news. Judging a serum on that number would have made us the thing we were built to catch.
Accomplishments that we're proud of
We shipped a product that can tell a user to wait, to skip a purchase, and to stop blaming a serum, and made those the main screens rather than the error states.
The same face runs a closed loop a retailer could actually operate. Measure the noise. Match the shade in CIELAB. Try the look. Bag it. Check the claim against the noise. Buy it. Start the protocol by voice from the watch. Read the night back from Health Connect. Refuse a verdict until the posterior clears the minimum detectable change. A seeded catalogue means a judge can walk that loop before a live scan exists, and the live path is still the one that spends YouCam units.
We also shipped the restraint. No invented community percentages. No clothing try-on glued on to look like eCommerce. No PDF. The shop earns its place because a purchase opens a test, and a shade is a distance in color space, not a recommendation with nothing underneath it.
The three devices are one account. The watch does not ask for a code. The phone is not a second design system. The laptop updates when the wrist buzzes.
What we learned
A skincare score is a measurement with an error bar, and the error bar is usually the whole story. Lighting, angle, sleep, and a hand on the face can move the number more than the bottle. The product people need is the one that shows the error bar and waits.
We also learned that honesty is a feature you have to engineer. It is the block list, the cache key, the dropped covariate, the sensor you leave out, and the simulation label you refuse to take off. A model that always has an answer is how you lose this category.
What's next for WorthIt
Put WorthIt at the moment of checkout for a real catalogue, with the brand's own claim as the effect size and the customer's noise floor as the bar. Keep the order. Start the trial the night it arrives. On the earliest honest day, tell them to repurchase or to stop, with the sentence still citing a raw score.
On the wrist, finish the gesture study until a raised hand and a face touch separate cleanly on that person's arm, and publish the matrix. Add beat-to-beat RMSSD only when the Health Sensor SDK is actually linked, still never estimated. Let a brand run the retail view across a panel of real noise floors and see how many mornings their claim would need before WorthIt would let them say it.
Built With
- android-studio
- framer-motion
- gsap
- jetpack-compose
- kotlin
- node.js
- open-meteo-forecast
- react
- supabase
- tailwind
- typescript
- vitest
- wearos
- youcam
