← back

lime

2026

an ai digital wardrobe that tells you what to wear

next.jsfastapigeminipineconesupabasevision-aivector-search

i built lime because i couldn't decide what to wear, and i was pretty sure i wasn't the only one. every morning is the same small task: stand in front of a closet, forget half of what's in it, fail to account for the weather, and settle for the same three outfits on rotation. that's a real problem, it's a real market (closet apps and styling services exist for a reason), and it was the right size to chase a third goal i cared about just as much: proving to myself i could design and ship a full-stack ai product solo, end to end, not just train a model in a notebook.

so lime does one thing: you take a phone photo of a piece of clothing, and it becomes a tagged, searchable entry in a digital closet. then it uses vector search and live weather to recommend outfits that actually go together. no manual data entry, no filling in forms about your shirts.

what i built

the piece i'm proudest of is the vision ingestion pipeline, because it's where the "no manual data entry" promise either holds up or falls apart. when you snap a photo of an item, a few things happen in sequence on the backend. first, briaai/RMBG-1.4 strips the background so the model sees the garment and not your bedroom floor. then gemini 2.0 flash tags it across five attributes: category, silhouette, palette, texture, and aesthetic. i forced that output through a pydantic schema so the model has to return structured, validated fields instead of a paragraph i'd have to parse and trust. finally the item gets embedded with all-MiniLM-L6-v2 into a 384-dimension vector and stored in pinecone for similarity search.

that ordering matters. background removal before tagging makes the tags cleaner. structured output before storage means a malformed gemini response fails loudly at ingestion instead of silently poisoning the closet. each step exists because the naive version without it produced worse data.

the recommendation side closes the loop. on the styling deck, lime pulls your local weather from open-meteo, turns the conditions into a natural-language description of an ideal outfit, and uses that to re-rank your actual wardrobe by aesthetic fit through vector search. the front end is a tinder-style swipe deck (tops, bottoms, shoes) so building an outfit feels like a game instead of a database query. supabase handles auth, the postgres database, and image storage, with row-level security so one user's closet stays their own.

architecture

the decision i'd defend hardest is splitting lime into two independently deployed services instead of one app. next.js owns the ui, auth, and orchestration. fastapi owns the entire ml pipeline and stays completely stateless. they're joined by a shared uuid and nothing else.

Browser --photo--> Next.js (Vercel)
  Next.js --POST /items/ingest--> FastAPI (HF Spaces)
    FastAPI --> RMBG-1.4 --> Gemini 2.0 Flash --> MiniLM embedding --> Pinecone
  FastAPI --tags + image--> Next.js --store--> Supabase

Browser --geolocation--> Next.js
  Next.js --GET /recommendations--> FastAPI
    FastAPI --> Open-Meteo --> Pinecone --ranked items--> Next.js

keeping fastapi stateless was the call that made the rest manageable. the ml service doesn't know about users, sessions, or the database; it takes an image or a weather string and returns tags or rankings. all the stateful, security-sensitive work lives in next.js and supabase. that separation let me deploy the heavy python ml service on hugging face spaces and the fast typescript front end on vercel, each scaling and failing independently.

the hard part

the struggle wasn't any single model. it was making four services talk to each other cleanly. next.js, fastapi, gemini, and pinecone (plus supabase and open-meteo) each work fine alone. getting an image to flow from a browser, through a vercel function, to a stateless python service on a different host, through a background remover and a vision model and an embedder, into a vector database, and then back as tags the front end could store, with weather data and vector rankings flowing the other direction, was the actual work. on a solo build there's no one to hand the integration to. the bug is always somewhere in the seams between services, and the seams are yours.

that's also where i learned the most. designing the contract between two services, deciding what each one is responsible for and what crosses the boundary, taught me more about building software than any individual api call did.

outcome

lime is live and running on a free-tier budget. the full pipeline works: ingest a photo, get it tagged and embedded, browse the closet, and get weather-aware outfit recommendations. the honest limitation is cost. the mvp runs on free api tiers, so rate limits and quotas cap how much it can do before the paid bills would start, and i built it to prove the system, not to absorb production traffic. everything that's throttled is throttled by billing, not by a gap in the build.

i'll also be straight about how it was made: i architected lime and made the design calls, and i used ai coding tools heavily through the build, which is how i shipped a four-service product solo as a student. the architecture documents in the repo (the system design, the product requirements, the cost analysis) are where my reasoning lives if you want to see the decisions behind the code.

what's next

the obvious next step is putting a card on the apis and letting the free-tier ceiling go, then seeing whether the recommendations hold up at real wardrobe sizes. past that, the interesting product question is personalization: right now lime ranks by aesthetic fit and weather, but a model that learns which of its suggestions you actually swipe right on would make it feel less like a tool and more like a stylist who knows you.