OutfitDB

OutfitDB v0.2.0

OutfitDB shows how anyone can build a personal database and train their own ML model for everyday problems that don’t have a tidy mathematical answer. Three short rating flows teach it your sense of temperature, your aesthetic, and your sense of occasion — and the recommendations even surface combinations from your own closet you’d never have thought of yourself. Local-first: your data never leaves your machine.

1-of-1
Built for one. You.
Tailored
Designed around your real life
Discovery
Combos from your own closet you’d never try
30 sec
From “nothing to wear” to ranked outfits
11
Tables in your own database
3 axes
Train weather, taste, occasion separately
Live
Wardrobe state in real time
0 cloud
Nothing leaves your machine

Live demo

The full FastAPI backend, deployed to a Render free instance and pre- seeded with the Tester wardrobe (54 items, 17 MB of photos). Every interaction hits the real Python service: SQLAlchemy talks to SQLite, XGBoost ranks outfits, Jinja renders templates, the lifespan hook copies the bundled seed into /tmp on each cold boot. The recommendation flow, profile switcher, training pages, calendar, context builder, and laundry/dirty/wear state machine all run end-to- end — this isn’t a static mock anymore.

Render’s free tier sleeps the instance after 15 minutes of inactivity, so the very first visit can take ~50 seconds while the container wakes up. Subsequent loads are instant. If the iframe doesn’t respond, open the demo URL directly — the wake-up takes the same time either way. Each cold boot wipes /tmp and re-seeds Tester from the bundled snapshot, so the demo always returns to a clean state.

What it does

You upload photos of your clothes once. The app learns three independent axes of preference from your ratings, then chains them at recommendation time so a single hard fail (wrong temperature, wrong occasion) drives the score to zero regardless of how aesthetically pleasing the outfit is.

Stage 1
Temperature
Six zones (subzero / cold / cool / mild / warm / hot). Multi-label classifier — one outfit can suit multiple zones.
×
Stage 2
Aesthetic
Pure look rating: color, cut, layering. User scores on a four-point scale ignoring temperature and occasion.
×
Stage 3
Occasion
Nine event types from gym to formal_event. Multi-label so one outfit can be wearable for multiple events.

The recommendation score multiplies all three signals with two soft factors (freshness, recovery) so the model both surfaces neglected items and respects pure-axis judgments.

Why local-first

The data the app collects — what you wear, what you don’t, what you rated “love” vs “hate” — is unusually personal. Hosting that on a shared server creates obligations (authentication, encryption at rest, GDPR-style data handling) that undermine the user’s trust without buying anything they need.

OutfitDB ships as a desktop app. Each user’s data lives in their own OS-standard application data directory (~/Library/Application Support/OutfitDB/profiles/{name}/ on macOS, %APPDATA%/OutfitDB/profiles/{name}/ on Windows), inside a single SQLite file plus an images folder. The app launches uvicorn bound only to 127.0.0.1, opens the system browser, and runs entirely on the user’s machine. Nothing crosses the network except the optional weather and geocoding lookups (both calls go from the user’s browser directly to the public APIs, never through any server I run).

Six implementation phases

Phase 1 — Layer Coverage Model

Thermal coverage formula T_cover = T_BASE − α·coverage with dual curves (comfort + aesthetic) determines optimal layer count for any temperature. Replaces hand-coded weather rules.

Phase 2 — XGBoost Preference

Per-user binary classifier on a 100-dimensional feature vector. Cold-start falls back to mean item rating; warm model swaps in once 10+ ratings exist.

Phase 3 — Local-First Storage

SQLite per-profile schema with idempotent ALTER TABLE migrations. Profile folders survive app updates because they live outside the bundle.

Phase 4 — Multi-Stage Training

Pure-axis labeling: three independent classifiers trained on disjoint rating tables. Inference multiplies the three probabilities so one bad axis kills the score.

Phase 5 — Discovery Polish

Fabric-blend composition (40/60 cotton/linen as weighted multi-hot), four-state lifecycle (clean / worn / in_laundry / unavailable), new-item priority training, force-anyway override for unusual outfits.

Phase 6 — Desktop Packaging

PyInstaller .spec handles the FastAPI-stack frozen-mode gotchas (Jinja2 paths, PIL plugins, xgboost native lib). Auto-update via cached public manifest. macOS DMG with drag-to-Applications layout.

Tech stack

FastAPI SQLAlchemy 2.x SQLite XGBoost NumPy Pillow Pydantic v2 Jinja2 vanilla JS Service Worker PyInstaller

macOS

  1. Click Download for Mac above. You’ll get OutfitDB-0.2.0.dmg.
  2. Double-click the DMG. A window opens showing OutfitDB.app next to an Applications folder shortcut.
  3. Drag OutfitDB.app onto Applications. Installed.
  4. Launch via Spotlight (⌘ Space → type “OutfitDB”), Launchpad, or Finder → Applications.
First launch only: macOS Gatekeeper blocks unsigned apps with “developer cannot be verified.” Right-click the app → Open → confirm. Subsequent launches work normally. This will go away once the app is code-signed in the future.

On first launch the app automatically seeds a Tester profile with 54 sample items (the same wardrobe used in the live demo above) so you can immediately click around the recommendation flow without having to upload your own clothes first. Add your own profile any time via the top-right user switcher; deleting Tester won’t bring it back on next launch (the seed only runs when the profile folder is empty). The app loads in your default browser at http://127.0.0.1:18888.

Windows

Grab the OutfitDB-0.2.0-windows.zip asset from the v0.2.0 release (or use the Download for Windows button at the top of this page). Unzip anywhere — e.g., C:\Users\<you>\Apps\OutfitDB\ — and double-click OutfitDB.exe. The app starts a local web server on http://127.0.0.1:18888 and opens it in your default browser.

First launch only: Windows SmartScreen blocks unsigned apps with “Microsoft Defender SmartScreen prevented an unrecognized app from starting.” Click More info → Run anyway. Subsequent launches work normally. This will go away once the binary is code-signed in the future.

The Windows build is produced by a GitHub Actions workflow (build-windows.yml) that runs pyinstaller outfitdb.spec on a windows-latest runner every time a v* tag is pushed to the source repo. Same wardrobe seeding flow as macOS — first launch auto-creates the bundled Tester profile.

If you’d rather build from source:

# Windows + Python 3.11 / 3.12
git clone https://github.com/chentzuyuan/OutfitDB.git
cd OutfitDB
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
pip install pyinstaller
pyinstaller outfitdb.spec --noconfirm
# Output: dist\OutfitDB\OutfitDB.exe

Database design

The full entity-relationship model, schema rationale, and migration strategy are documented in the EPPS 6354 Information Management Final Report →. That page is the formal academic deliverable for the course; this page is the end-user-facing landing page for the application itself.

Source & documentation

Source is on GitHub at chentzuyuan/OutfitDB. A formal technical writeup of the system — schema, three key design decisions, ML pipeline, and deployment — is available as a PDF and as a web section:

Final Report PDF → Web version →
← Back to home