Inspiration
Every shopping app is built to make you buy more. We wanted the opposite: the stylist who works for you, not the store.
Hollywood stars have image-engineering teams that analyze their bone structure, contrast, and proportions before a single garment is approved. The rest of us guess — and our closets fill up with "it looked great in the photo" mistakes. MOONIE V democratizes that team: a Visual Calibration System that lives in your chat, learns your visual structure from a few photos, and acts as a purchase gatekeeper. Its core metric is not conversions. It is wrong purchases prevented.
What it does
You upload a few unfiltered photos. MOONIE V builds a five-variable structural profile:
| Variable | What it captures |
|---|---|
| VAR_1 Contrast | Low / Medium / High |
| VAR_2 Undertone | Cool / Neutral / Warm |
| VAR_3 Face structure | two axes: edge geometry (Straight/Blended/Curved) × spatial distribution (Compact/Balanced/Dispersed) |
| VAR_4 Frame type | Linear / Moderate / Broad |
| VAR_5 Body ratio | Vertical-dominant / Balanced / Horizontal-dominant |
Then you screenshot any product — from any shopping app, web store, or a photo taken in a physical shop — and drop it into the chat. The engine runs a hard-ordered evaluation: fabric–structure compatibility first, skeletal weight override, proportion strategy, red sensitivity, and only then color. Color is step 5, never step 1 — because our core rule is that color cannot rescue structure. A clinging Class-A knit on a soft-diffuse facial structure is a structural conflict; "get it in black" doesn't fix it, so MOONIE V refuses to say it does.
Every item gets one of four verdicts — ✔ Recommended / △ Playable / ◎ Photo-only ("photographs well, wears badly") / ✘ Not advised — with the blocking factor, conditions, and a confidence grade. And thanks to our stability rule (Patch 9), pushing back doesn't flip the verdict: Moonie will validate your instinct and explain, but it won't cave. No one pays a consultant to be flattered.
Privacy is structural, not a promise: your photos and profile live in your own Google Drive (drive.file scope), the model key never leaves the server, and the app stores only file IDs.
How we built it
- Stack: Next.js 14 (App Router) + TypeScript + Tailwind on Vercel; edge API routes as thin shells; a strictly layered
lib/—protocol/(the crown layer),ai/,storage/,quota/— with one-way dependencies enforced by review. - The Protocol as code, not vibes: MOONIE Protocol v1.0 is a versioned rule engine (
rules.ts+ prompt assemblers + CHANGELOG). The system prompt is assembled per user: universal engine rules → the conditional rules matching this profile's coordinates → personal fit rules → product rules → a rule-coverage discipline that forbids the model from improvising rules for coordinates we haven't defined yet — it must cap confidence at Low and say so honestly. - Structured output: the model returns strict JSON (verdict / blockingFactor / conditions / analysis / confidence); the elegant prose is a rendering layer. Less freedom for the model = more stable judgments.
- Codex as an independent audit officer: this is the part we're proudest of. We ran a two-agent development loop where one AI implements and Codex CLI reviews every work package adversarially — read-only
codex execaudits against the spec, findings filed as BLOCKER/MAJOR/MINOR, a ticket state machine (TODO → REVIEW → FIXING → APPROVED) with a circuit breaker that escalates to the human producer after two review rounds. Codex also independently recalculates the golden test set whenever the protocol changes. The rule that made it work: the reviewer is never the author of the fix. - Golden set as CI: eight fixture cases (real product photos + synthetic profiles + expected verdicts, each anchored to specific rule IDs) run as a regression gate. A verdict flip is treated as a build failure.
Challenges we ran into
- Verdict drift is the AI-native form of tech debt. Promising "the verdict won't change" while sitting on a stochastic model is an engineering problem: pinned model version, temperature 0, structured JSON, and the golden regression set. Traditional tests catch broken code; golden sets catch a system that quietly changed its mind.
- Red-teaming our own rules. We attacked the protocol with adversarial cases — including prompt-injection attempts stored right next to the fixtures (
attack.txt) — and surviving attacks were promoted into golden cases. One audit round caught the model inventing exemptions to bypass a hard rule; that failure mode is now a permanent test. - Honesty engineering. The hardest prompts weren't about being smart — they were about being honest: distinguishing "your photos aren't enough" from "our rules don't cover your coordinates yet," and saying each in warm, human language without dressing up a gap as reassurance.
- Unglamorous warfare: e-commerce CDNs TLS-fingerprint non-browser clients (fixture images had to be captured via real-browser response interception), and iCloud kept eating
node_modulesand resurrecting deleted files into commits. Every scar became a documented rule.
What we learned
The moat of an AI product isn't the UI — it's a versioned, testable, red-teamed rule system and the discipline around it. Multi-agent adversarial review genuinely catches author blind spots that single-agent development cannot. And "code only lives in git": anything that exists only in a chat log is code that has already been deleted.
What's next
Wardrobe management on top of the same protocol (your evaluations become a living closet), the fit-rules layer opened to every user, real-user validation of our favorite metric — "when Moonie said no, did you agree?" — and an iOS share extension so any product screen anywhere is two taps from a verdict.
Built With
- codex
- eslint
- github-actions
- google-drive-api
- gpt-5.6
- json-schema
- next.js
- node.js
- openai
- playwright
- react
- tailwind-css
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.