Your digital wardrobe. Your style, planned.
Pick Your Fit is a full-stack web application that turns a physical wardrobe into a digital one: you scan your clothes once, the app automatically recognizes their category, and you get outfit suggestions and the ability to plan them on a calendar without ever pulling anything off a hanger.
It started with a mundane but recurring frustration: packing for a trip.
At the beginning of July 2026, while getting ready for a trip to Rome, I did what I always do: took almost everything out of my wardrobe and still couldn't find anything I actually loved. The problem was never a shortage of clothes; it was the absence of any structured overview of what I already owned and how those pieces could be combined.
"What if my whole wardrobe lived in one place, and I could plan outfits without ever pulling a single thing off its hanger?"
That question is where Pick Your Fit began: an app where you digitize your wardrobe once, item by item, and then get outfit suggestions on demand, removing both the guesswork and the time lost in the process.
| Before | After |
|---|---|
| "I have nothing to wear." | Open Pick Your Fit |
| 45+ minutes lost searching | Find what you love in seconds |
| A messy room, every time | Create the perfect outfit |
| Overpacking for every trip | Pack only what you need |
| Stress before every trip | More time for the trip itself |
Pick Your Fit is built for anyone who has ever said "I have nothing to wear," has plenty of clothes but still feels stuck, loves traveling and packing smart, wants to save money, or simply wants a more organized life.
Before any outfit-generation logic could be built, the app needed one core capability: to automatically determine, from a photograph alone, what type of garment it depicts. This piece was validated separately, in a proof-of-concept project called What A Blouse / PICKyourFIT (classifier), which isolates exactly this problem:
- An image classification model trained with Google Teachable Machine, exported as a TensorFlow.js model and run entirely in-browser (no server, no image upload for inference).
- A manually assembled dataset, with a minimum of 30 representative photographs per category (T-shirt, blouse, shirt, jacket, blazer, pullover, hoodie, crop top, turtleneck, tank top, shorts, pants, skirt, tights, leggings, dress, bodysuit, jumpsuit, romper, socks, boots, sneakers, heels, glasses, plus a dedicated category for images that are not clothing at all).
- An entropy-based confidence mechanism, which addresses a structural limitation of any classifier: it will always output a probability for every class it was trained on, even for images with no relation to those classes (a wall, an animal, a face).
How the entropy check works:
For a probability distribution p1, p2, ..., pn over n classes, Shannon entropy is defined as:
H(p) = - sum(pi * log2(pi)), for i = 1 to n
The theoretical maximum occurs when the distribution is perfectly uniform (pi = 1/n for all i):
H_max = log2(n)
Normalizing gives a value between 0 and 1:
H_norm = H(p) / H_max
- H_norm close to 0 -> concentrated distribution -> confident prediction (likely a real garment).
- H_norm close to 1 -> uniform distribution -> total uncertainty (likely not clothing).
Thresholds used:
- If
H_norm < 0.80, the image passes the "is this clothing at all" check. - If the highest individual class probability is at least 72%, the prediction is shown directly.
- If it falls below 72%, the interface shows several candidate categories with their confidence percentages and lets the user make the final call.
This proof-of-concept had no backend, database, or persistence: the wardrobe existed only in browser memory, for the duration of the session. Its sole purpose was to validate the classification pipeline before it became the foundation of the full application, Pick Your Fit.
Every scan runs the same five steps, whether the user is a guest or logged in:
- Upload photo: take or upload a photo of the item.
- Teachable Machine: the trained model analyzes the image.
- Category prediction: the algorithm predicts the most likely category.
- Review and edit: confirm or manually correct the category.
- Save to wardrobe: add the item if logged in.
Under the hood: Google Teachable Machine (classification), remove.bg (background removal), Firebase (auth and data), Cloudinary (image storage).
- Unlimited clothing organization (for verified accounts).
- Instant search across the whole closet.
- Filter by category.
- Mark favorite pieces.
- Outfit suggestions generated from what the user already owns.
- Each item can be annotated with a brand name and a short description.
- The background of every image is automatically removed before saving, so each item is stored isolated on a transparent background.
- Drag and drop pieces from the wardrobe onto a canvas, the way you'd lay an outfit out on a bed.
- Create and save an unlimited number of outfits (verified account).
- Edit an existing outfit later, or duplicate it as a starting point.
- Every outfit created is stored in the user's personal gallery.
- Open any outfit to edit it, favorite it, or plan it on the calendar.
- Assign an outfit to any day on the calendar.
- Avoid accidentally repeating the same outfit.
- Plan holidays, work weeks, or a single trip.
- See every upcoming outfit at a glance.
- Every outfit ever created stays on record.
- Browse previous months and years at any time (e.g. 2026, Summer, July: 31 outfits).
- Report a bug, ask a question, or send a suggestion directly to the team.
- A community space for sharing ideas, fashion inspiration, and general discussions.
- No images are shared publicly.
- Only the account owner can access their wardrobe.
- One-click account deletion, with a permanent cascade delete of clothing, outfits, favorites, calendar, profile, and account information.
| Level | What you can do |
|---|---|
| Guest (no account) | Scan clothes and get AI recognition; browse the landing page and features; read about the app, reviews, contact info. Cannot save anything: everything is lost at the end of the session. |
| Registered (email not confirmed) | Can save clothes to the wardrobe, but everything is capped: 2 items per category, 2 favorites, 2 planned outfits, until the email is confirmed. |
| Verified (email confirmed) | Unlimited wardrobe and favorites; unlimited outfit planning and calendar; full archives and statistics; everything unlocked, no limits. |
The cap on unconfirmed accounts is enforced at the backend level, across all route files, not just in the UI, so the limits cannot be bypassed with direct API calls.
Frontend
- HTML, CSS, and vanilla JavaScript, multi-page (no framework)
calendar-core.js/calendar-picker.js: shared modules for calendar views (week/month/year)- Google Fonts: Fraunces, Inter, JetBrains Mono
Backend
- Node.js and Express
- Authentication: Firebase Authentication (JWT passed as a Bearer token in authorization headers)
- Database: Firebase Firestore: profile, wardrobe item metadata (brand, category, description, createdAt), outfits, favorites, calendar
- Firestore security rules: each user can read, write, or delete only their own data
Images
- Cloudinary: storage and encrypted CDN delivery for avatars and wardrobe photos, organized under a
wardrobe/{uid}folder - remove.bg (Kaleido AI), called through a secure backend proxy, for automatic background removal (ephemeral processing, no image retention by the third party)
- Avatar images are cropped and optimized client-side (Cropper.js) to 512x512px, JPEG, 88% quality
Hosting and infrastructure
- Backend deployed on Render (free tier)
- Source control on GitHub
- Account data: first name, last name, email.
- Authentication: hashed password (Firebase), IP address logged temporarily at sign-up to enforce a 2-accounts-per-IP limit.
- Local session:
pyf_idToken,pyf_uid,pyf_userPhotostored in LocalStorage (strictly functional, no tracking or advertising cookies) - Account deletion (cascade delete): irreversibly removes the wardrobe from Firestore, images from Cloudinary, the profile document, and credentials from Firebase Authentication, plus local browser data. The process cannot be undone and no backups are kept.
- Minimum age: 13 (16 within the EU/EEA), per GDPR/COPPA.
- Node.js 18+ and npm
- A Firebase project with Authentication (Email/Password) and Firestore enabled
- A Cloudinary account (cloud name, API key, API secret)
- A remove.bg API key
# 1. Clone the repository
git clone https://github.com/dariadraghici/PICKyourFIT
cd pick-your-fit
# 2. Install dependencies
npm install
# 3. Create your local environment file
cp .env.example .env
# then fill in the values described in "Environment Variables" below
# 4. Add your Firebase service account credentials
# Download the service account JSON from Firebase Console
# and place it as described in your .env (or as serviceAccountKey.json,
# depending on how firebase-admin is initialized in the project)
# 5. Run the app in development mode
npm run dev
# App will be available at:
# http://localhost:3000The frontend is plain HTML/CSS/JS and is served statically by the Express backend, so no separate build step is required. Once the server is running, the pages are available at the same host and port.
Create a .env file in the project root with the following keys:
# Server
PORT=3000
NODE_ENV=development
# Firebase (client SDK config, used by the frontend)
FIREBASE_SERVICE_ACCOUNT=
# Firebase Admin SDK (server-side, for Firestore + token verification)
FIREBASE_WEB_API_KEY=
# Cloudinary
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
# remove.bg
REMOVE_BG_API_KEY=
#hCAPTCHA
HCAPTCHA_SITE_KEY=
HCAPTCHA_SECRET=Notes:
FIREBASE_PRIVATE_KEYusually needs its newline characters escaped (\n) when stored in a single-line.envvalue.- Never commit
.envor any service account JSON file to source control; make sure both are listed in.gitignore. - The
IP_ACCOUNT_LIMITvariable reflects the 2-accounts-per-IP rule described in the Privacy section above and can be adjusted for local testing.
Active areas of work include:
- Email verification with per-feature caps for unverified accounts, enforced consistently across all backend route files.
- A fix for a stale JWT token bug affecting session refresh.
- UI refinements: a responsive profile page grid, a "Currently Planned Outfits" section, mini-stat blocks.
- The earlier migration of calendar and favorites data from LocalStorage to Firestore, using Bearer-token-authenticated fetch calls.
- Replacing ephemeral storage on Render's disk with Cloudinary, for real persistence of avatars and wardrobe photos.
Built by Daria-Ioana Drăghici - for everyone who has ever said "I have nothing to wear."