Skip to content

Work/Rhovie

Rhovie

An AI skincare coach. A face scan reads your skin across texture, hydration, wrinkles and pigmentation, and every scan is saved, so progress is visible instead of imagined.

ROLE
Development
YEAR
2025–2026
PLATFORM
iOS
STATUS
Live on the App Store
Rhovie — The scan, gated on light and framing

The scan, gated on light and framing

01 / 07

Screen 1 of 7: The scan, gated on light and framing

The problem

Skincare is guesswork. You buy something, use it for weeks, and never find out whether it did anything.

Rhovie starts with a face scan that reads skin across four axes, estimates skin type, and builds a morning and evening routine around the products you already own. Every scan is stored with its image, its scores and the conditions it was taken in, so the second scan is the one that actually tells you something.

The interface was designed by Artur Moldovanu, my business partner. I built the product: the scan pipeline, the Firebase backend, the anonymous-to-permanent account model, the Cloud Run analysis service, the release process and the store submission.

The hardest constraint was honesty. It would have been easy to return a confident number from any photo. Returning nothing, and explaining why, turned out to be the feature that made people trust the rest of it.

The result

Live on the App Store, and still getting updates. The interface design is Artur Moldovanu's; everything that runs underneath it is mine.

STATUS
Live on the App Store
PLATFORM
iOS
SHIPPING SINCE
2025
The product

Three screens carry it.One device, three states.

Rhovie — state 3

STATE 01 / 03

The scan

The camera will not let you waste a scan. One face, framed large enough, held close to straight, and lit without glare or blur: all of it checked before the shutter is enabled. If something is wrong, the app names which of the twelve checks failed rather than returning a confident number from a bad photo.

Rhovie — state 8

STATE 02 / 03

The routine

Analysis returns four axes and an estimated skin type. The routine is then assembled from products the user already owns, with gaps flagged rather than quietly filled with things to buy.

Rhovie — state 9

STATE 03 / 03

The record

Every scan is stored with its image, its scores and its conditions. The point of the app is the second scan, the one that tells you whether any of it worked.

Under the hood

Two decisions worth explaining.The parts that took the longest.

D—01

Refusing the bad photo

A scan costs the user something: time, and on the free tier one of a small number of credits. Returning a confident score from a dark, angled photo is worse than returning nothing at all.

So the gate runs on-device before the shutter is enabled: exactly one face, big enough in frame, within 12° of yaw, 10° of pitch and 8° of roll, and a lighting signal clear of underexposure, glare and blur. Twelve distinct issues can block the shutter, and the camera names the one it hit.

faceQuality.tsTS
// every frame, before the shutter unlocksconst straightEnough =  Math.abs(face.yawAngle) <= MAX_YAW &&  Math.abs(face.pitchAngle) <= MAX_PITCH &&  Math.abs(face.rollAngle) <= MAX_ROLL if (signal.highlightRatio > MAX_HIGHLIGHT_RATIO)  issues.push('glare_detected')// usable only when issues is empty, no credit spent

D—02

Carrying a stranger's history

You can scan before you sign up. That was the right product decision and the hardest engineering one. By the time someone creates an account they may already have a month of scans attached to an anonymous identity.

Credential linking keeps the UID, but storage paths, Firestore documents and entitlement records all had to move as one unit. It is a single batched transaction with an idempotent retry: if it fails halfway, nothing moves.

linkAccount.tsTS
// anon:7f2a… → user:7f2a…, uid preservedawait linkWithCredential(anonUser, cred) const batch = db.batch()moveScans(batch); moveRoutines(batch)moveEntitlements(batch) // all of it, or none of itawait batch.commit()

WHAT IT IS BUILT ON

CLIENT
React Native · Expo SDK 54 · TypeScript strict · Zustand · Zod
BACKEND
Firebase Auth, Firestore and Cloud Storage · Cloud Run analysis service
VISION
Vision Camera · ML Kit face detection · MediaPipe face mesh
OPERATIONS
Sentry · EAS Build · App Store Connect · TestFlight

CREDITS

Product and interface design by Artur Moldovanu. Development, backend, vision pipeline, release engineering and store submission by me.


STATUS

Live on the App Store and in active development.

NEXT PROJECT

TeamTipOut

Tipout calculator for restaurant teams. Time-weighted splits, saved crews, and an export the whole shift can see.

Taking on new projects

Tell me what you’re building.A written scope and a fixed quote before any money moves.

I reply to everything within one working day. If I’m not the right person for it, I’ll tell you straight away rather than three weeks in.