Photograph your clothes once. Get a reasoned outfit every morning.
A private, self-hosted wardrobe assistant that reasons from the menswear canon — and tells you when your outfit doesn't work.
Flusser · Derek Guy · Permanent Style · Gentleman's Gazette
Why it's different · What it does · Setup · Cost · Architecture
Doesn't work — "Airport lounge in beige — comfortable, camouflaged, no edges anywhere."
Biggest problem: Sage-taupe over khaki under tan is three warm mid-values at nearly identical lightness, so the whole silhouette flattens into one beige column and your face has nothing to sit against.
What I'd change: dark indigo below — the value break the whole thing is missing.
That's Valet judging a real outfit. Not "try adding a pop of colour."
Most "AI stylist" apps are a colour wheel and a vibe. They tell you navy goes with grey and stop there. Ask one whether your outfit is any good and it will tell you it looks great.
Valet is built on a structured rule set compiled from the people who actually wrote the book:
| Source | What it contributes |
|---|---|
| Alan Flusser, Dressing the Man (2002) | Complexion contrast, the picture-and-frame model, proportion checkpoints, pattern-scale arithmetic, hosiery and leather rules |
| Gentleman's Gazette | The formality scale and per-category rankings |
| Derek Guy (Die, Workwear!) | Register coherence, drape, casual fit, jacket length by build |
| Simon Crompton (Permanent Style) | Cloth weight, weave openness, seasonality |
| Bespoke Unit | The contrast system, operationalised |
Principles were extracted and restated — no book text is reproduced or shipped.
1. Complexion contrast. Flusser's central claim is that an outfit should echo the contrast between your own hair and skin. It's why the same navy jacket flatters one man and flattens another. Almost no styling tool models it; Valet asks for it in the first thirty seconds and applies it to everything.
2. Register, as a second axis. Formality tells you how dressed up a piece
is. It cannot tell you what it is. A suede bomber and a technical puffer can
both score "3" and still fight each other. Every garment carries a register —
tailored · workwear · sportswear · street · technical · classic — and outfits
are checked on both axes.
It's also told, explicitly, not to sugarcoat. If a combination is weak it says so and names the mechanism.
| Today | Weather, your day in your own words, 2–8 outfits |
| Closet | Everything you own, searchable, fully editable |
| Build | Pick an outfit yourself, have it judged |
| Saved | Keep the looks that worked |
| Talk | Argue with it about a combination |
| Add | Photograph garments, catalogued automatically |
Each morning's outfits come with mechanism tags, one line on why it's strong, a do and a don't, a formality read written against the fear of being overdressed, and an honest verdict on whether it actually beat your fallback.
Build is the inverse: you assemble, it judges. Verdict, vibe, green flag, red flag, and concrete swaps drawn from your own wardrobe.
You need a Netlify account (free tier is fine) and an Anthropic API key.
git clone https://github.com/macmenes/valet.git
cd valet
npm install
netlify sites:create --name your-valetSet four environment variables:
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY |
The daily recommendation, critique and chat |
VALET_PASSPHRASE |
Gates every API endpoint — not optional |
NEURALWATT_API_KEY |
Optional. Cheap vision for bulk tagging |
TAG_PROVIDER |
anthropic (default) or neuralwatt |
netlify env:set ANTHROPIC_API_KEY "sk-ant-..." --secret
netlify env:set VALET_PASSPHRASE "something-long-and-unguessable" --secret
npm run build && netlify deploy --prod
VALET_PASSPHRASEis not optional. A Netlify deploy is a public URL. Without it, anyone who finds your site can spend your API credits. The functions fail closed — unset, they return 503 rather than running.
Open the site in Safari (only Safari can install to the iOS home screen), then Share → Add to Home Screen. It launches full-screen.
netlify dev # serves the app and the functionsnpm run dev runs the UI alone; API calls will 404.
Photographing 150 garments through a phone UI is how people give up. Point the script at a folder instead:
export VALET_URL=https://your-valet.netlify.app
VALET_PASSPHRASE=... node scripts/bulk-import.mjs --dir ~/Pictures/closet- Handles HEIC straight off an iPhone
- Resumable — checkpoints after every garment, so a dropped connection costs one item, not the closet
--only-newtags just what you've added since last time- Writes chunked JSON you import in the app (You → Import backup)
Then You → Sync moves the closet between devices via your own Netlify Blobs store.
| Action | Roughly |
|---|---|
| Cataloguing one garment | ~8¢ (Claude) or ~0.1¢ (NeuralWatt) |
| A morning's outfits | ~33¢ |
| Judging one outfit in Build | ~17¢ |
About $10/month at one recommendation a day. Output tokens dominate —
thinking bills as output. To cut it: fewer options, or point the daily call at a
cheaper model in netlify/functions/lib/anthropic.ts.
Takes 2–3 minutes to produce a morning. That's the cost of reading a whole wardrobe and reasoning over it; it isn't a bug, and it can't be optimised away without making the advice worse. Turn on auto-start under You and it runs while you're reading the weather.
Add → photo downscaled on-device → /api/tag → structured attributes
↓ ↓
IndexedDB (photos + tags, local) ←────────────┘
Today → text catalogue + profile + weather + occasion
→ /api/recommend-background → Netlify Blobs → client polls
- Storage — IndexedDB. Photos never leave the device unless you enable sync.
- Sync — optional, via Netlify Blobs on your own site, behind your passphrase.
- Weather — Open-Meteo. No key, no account.
- Long calls run as background functions. Netlify terminates synchronous functions at 26 seconds; a real recommendation takes 150. Jobs write to a blob and the client polls, so leaving the tab or reloading doesn't lose a paid result.
netlify/functions/
lib/knowledge.ts the canon, as a structured rule set — the brain
tag.ts photograph → structured garment
recommend-background.ts the morning call
critique-background.ts judging an outfit you built
chat.ts conversation
sync.ts device sync
src/
views/ Today, Closet, Build, Saved, Talk, Add, You
db.ts IndexedDB
api.ts client, catalogue builder, job polling
scripts/
bulk-import.mjs catalogue a folder
backfill-register.mjs add register to an existing closet
lib/knowledge.ts is the interesting file. It's the rule set — contrast,
formality, proportion, pattern scale, cloth, register — with provenance in the
header. Edit it and the advice changes.
- Set your contrast honestly. Daylight, a mirror. It changes everything downstream.
- Photograph in daylight. Colour is the one thing that can't be recovered from a bad photo, and colour is what the system runs on.
- Correct the formality scores. That number gates which pieces can appear together; an inflated one quietly degrades every future suggestion.
- Mark the pieces you hesitate over as Unsure. It won't hide them — it tells the recommender to unlock them deliberately, anchored by things you trust, and to explain what makes them work. This is the feature that turns a catalogue into something useful.
- Write notes on garments. "Collar sits badly under a jacket", "runs small", "only works with the dark jeans". The recommender reads them.
- Log what you wear. It's the only signal that distinguishes what you chose from what was merely proposed.
- Browser storage isn't guaranteed. Safari can evict IndexedDB under pressure. Export backups, or turn on sync.
- One garment per photo. More than one and it tags the most prominent.
- Fabric weight is a guess. You can't see gsm in a photograph, and it says so rather than inventing precision.
- No shopping. It'll name the most useful gap in your wardrobe and then stop. It is not an affiliate funnel.
MIT. See LICENSE.
Not affiliated with any author or publication named above. Their ideas are credited because the advice would be worthless without them.
