I dress like a developer. Meaning: I think I'm fine until someone takes a photo of me at an event and I look like I raided a lost-and-found bin.
The real problem isn't that I don't care — it's that I don't have a framework for why something works or doesn't. I can't look at an outfit and tell you the color theory. I don't know what “occasion fit” means for a business casual dinner vs. a casual Friday. I just grab what seems okay and hope.
So I built the tool I actually needed: upload a photo, get brutally honest AI feedback.
The Core Insight
Fashion advice on the internet is mostly vibes. YouTube videos 12 minutes long. Reddit posts where the consensus is “it depends.” What I wanted was structured output: a score, a reason, and a specific next purchase.
The insight was treating outfit analysis like a rubric, not a conversation. Instead of “what do you think of this outfit?”, you ask “score this on four dimensions and return JSON.” That's the difference between a chatbot and a tool.
Technical Decisions
Stack: Next.js 15 + Tailwind v4 + shadcn/ui + TypeScript. This is my default now. Zero regrets, builds fast, looks professional.
Vision API: OpenAI's gpt-4o with a structured prompt and JSON response mode. The trick is giving it explicit scoring criteria:
const systemPrompt = `You are a professional fashion stylist.
Analyze the outfit and respond with valid JSON only:
{
"overallScore": number (0-100),
"feedback": "2-3 sentences of direct, specific feedback",
"colorAnalysis": {
"palette": [{"hex": "#XXXXXX", "name": "..."}],
"harmony": string,
"suggestion": string
},
"occasionScores": { "work": number, "dateNight": number,
"casual": number, "formal": number },
"shopPicks": [{ "item": string, "reason": string, "priceRange": string }]
}`;Structured output mode means I never have to parse freeform text. It either returns valid JSON or throws — which I handle gracefully with a fallback to demo data.
The upload flow was the messiest part. I went through three approaches before landing on a simple FileReader → base64 → API route pattern. Server-side handles the OpenAI call so the key never touches the client.
const base64Image = body.image.split(',')[1];
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{
role: 'user',
content: [
{ type: 'image_url',
image_url: { url: `data:image/jpeg;base64,${base64Image}` } },
{ type: 'text', text: 'Analyze this outfit.' }
]
}],
response_format: { type: 'json_object' }
});Demo data: I pre-loaded four “Recent Looks” with real scores, feedback, and shopping picks. The app never looks empty. This is non-negotiable — empty states kill conversion and make it feel unfinished.
What Surprised Me
How good the color analysis actually is. I expected vague responses like “the colors clash.” Instead it correctly identified that two greens in the same look were analogous (good) but both desaturated (problem), and suggested a warm accent to break the monotony. That's actual fashion knowledge.
The occasion scoring was also more nuanced than expected. It picked up on things like “this works for casual but the silhouette reads too relaxed for a business dinner.” It's not just vibes — it's reading context.
What I'd Do Next
- 1Real shopping links — right now picks are descriptive, not purchasable. Plugging in an affiliate API (ASOS, Nordstrom) would make this monetizable overnight.
- 2Wardrobe history — log your looks over time, see your style evolving, spot patterns.
- 3Before/after mode — upload two outfits, compare scores, see which lands better.
- 4Mobile-first sharing — the real use case is 'I'm about to leave, is this okay?' needs to be a 10-second flow.
Try it yourself
The app is live. Upload anything — gym clothes, a suit, your most chaotic festival outfit. It handles it all.
👉 outfit-analyzer.vercel.app →Fair warning: it doesn't sugarcoat. If your belt doesn't match, it will tell you. That's the point.