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.
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.
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
macOS
- Click Download for Mac above. You’ll get
OutfitDB-0.2.0.dmg. - Double-click the DMG. A window opens showing OutfitDB.app next to an Applications folder shortcut.
- Drag OutfitDB.app onto Applications. Installed.
- Launch via Spotlight (
⌘ Space→ type “OutfitDB”), Launchpad, or Finder → Applications.
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.
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.exeDatabase 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: