2025

Aesthetix

Two photos become a scored physique report — muscle groups, symmetry, V-taper, body fat — then a coach and a history that tracks the next scan against the last.

React NativeExpo 54TypeScriptZustandNativeWindReanimatedSupabaseGPT-4o VisionRevenueCat
Aesthetix progress chart
Aesthetix home score screen
Aesthetix AI coach chat

The product

People who train seriously still judge progress from the mirror or a gym selfie. Aesthetix is a physique-analysis app: a front and back photo become a structured report in about a minute — scores for eleven muscle groups, composite metrics (symmetry, V-taper, posture, proportions, athleticism, aesthetics), a body-fat estimate, and written priorities for what to train first.

The home screen is one 0–100 physique score, with a rank, streak and XP, and the three weakest focus areas. History and Progress chart score, body fat, and V-taper across scans, so the next photo is compared to the last instead of sitting in a camera roll. Coach is a chat that has already read the latest report — cut versus bulk, calories, what to train — behind Starter, Pro, and Max. The public site sends people to the App Store and Google Play.

My role

Solo build end to end: the React Native / Expo app, the Supabase backend (auth, Postgres, Edge Functions), the GPT-4o Vision scoring pipeline, the RevenueCat paywall, and the marketing site that has to get someone from an ad into a store.

Aesthetix progress screens on three phones

How it's built

React Native on Expo 54, TypeScript in strict mode, Zustand for state, NativeWind for styling, Reanimated for the radar chart and circular-progress rings. Supabase is the backend. GPT-4o Vision does the visual read; it never emits the final 0–100 number. RevenueCat owns the subscription tiers.

Aesthetix physique report and history screens

Decisions

1. GPT-4o never returns the final score

The model is prompted for coarse 0–5 ordinal ratings per muscle group and category — never a 0–100 number. A hand-tuned non-linear curve maps those ordinals onto the scale the UI shows. Categories are blended with a harmonic mean, so one weak area actually pulls the composite down the way a human judge would, and a body-fat modifier adjusts the result. Keeping the LLM out of the final-number business makes the score reproducible and tunable without re-prompting.

2. The OpenAI call moved server-side after a real exposure

The API key was originally called from the client via an EXPO_PUBLIC_OPENAI_API_KEY env var — which meant it shipped inside the app bundle. It now lives only as a Supabase Edge Function secret. The client never sees it.

3. Gamification state is enforced server-side

XP, streaks, and the free-scan limit are written through Postgres RPCs gated by row-level security, not incremented in local state. A user can't spoof scan counts by tampering with the app. Free-scan abuse is checked separately with a salted hash of device ID plus IP bucket.

Aesthetix Online on a laptop