Built for Problem Statement 2 — Personalised Experiences at Scale · GirlCode Hackathon
StyleSense is a full-stack fashion personalisation prototype that uses AI and behavioural data to deliver uniquely tailored shopping experiences. In 30 seconds — via a 4-question style quiz — it builds a complete style vector for a user and uses that to rank products, suggest outfits, and provide personalised AI fashion advice in real time.
No purchase history needed. No account required. Privacy-first by design.
| Feature | How it works |
|---|---|
| Style Quiz Onboarding | 4 questions capture style personality, colour palette, occasion, and size |
| Personalised Feed | Content-based filtering ranks all products against the user's style vector |
| Persona Switching | Switch between Sneha (casual) and Priya (formal) to see the algorithm in action |
| AI Style Advisor | Claude (Anthropic) gives personalised fashion advice specific to your profile |
| Smart Outfit Complements | Cart engine suggests cross-category pairings (top → bottoms only, never top→top) |
| Real-Time Feed Shift | Contextual bandit re-ranks the feed the moment you add something to cart |
| Repeat-Buy Detection | Items bought before show badges with one-click reorder |
| Privacy Modal | Full transparency — see every signal used, toggle each one, clear all data |
final_style/
├── README.md
│
├── backend/ # Python · Flask REST API
│ ├── app.py # App factory, blueprint registration, port 5001
│ ├── requirements.txt
│ ├── routes/
│ │ ├── products.py # GET /api/products
│ │ │ # GET /api/products/<id>
│ │ ├── recommendations.py # POST /api/recommend (content-based)
│ │ │ # POST /api/recommend/collab (collaborative)
│ │ │ # POST /api/recommend/complements
│ │ │ # POST /api/advisor (Claude AI)
│ │ └── users.py # GET /api/users
│ ├── models/
│ │ ├── content_filter.py # Weighted style-vector scoring
│ │ ├── collaborative.py # Co-purchase graph filtering
│ │ └── style_advisor.py # Claude prompt builder + response handler
│ ├── data/
│ │ ├── products.json # 15 fashion products with full metadata
│ │ └── users.json # User profiles (Sneha, Priya)
│ └── utils/
│ └── helpers.py # load_products(), success(), error()
│
└── frontend/ # React 18 · Vite
├── index.html
├── vite.config.js # Proxies /api → localhost:5001
├── package.json
└── src/
├── main.jsx # ReactDOM entry point
├── App.jsx # Root state + screen router
├── api.js # All fetch helpers (with offline fallback)
├── styles/
│ └── global.css # CSS variables + all component styles
├── data/
│ ├── products.js # Static fallback product catalog
│ └── personas.js # Sneha & Priya profile objects
├── hooks/
│ ├── useProducts.js # Loads from API once, falls back to static
│ └── useToast.js # Toast state with auto-dismiss
└── components/
├── Nav.jsx # Sticky nav, persona toggle, cart badge
├── QuizScreen.jsx # 4-step style onboarding
├── HomeScreen.jsx # Ranked product grid + filter chips
├── ProductCard.jsx # Card with fixed image containment
├── PDPScreen.jsx # Product detail + AI Style Advisor
├── CartDrawer.jsx # Slide-out cart + outfit complements
├── PrivacyModal.jsx # Data controls with toggles
└── Toast.jsx # Notification component
- Python 3.8+
- Node.js 18+
- npm
cd final_style/backend
pip install -r requirements.txt
python app.py
# API running at http://localhost:5001cd final_style/frontend
npm install
npm run dev
# App running at http://localhost:3000Vite automatically proxies all
/api/*requests tolocalhost:5001— no CORS configuration needed.
Go to http://localhost:3000 and complete the style quiz to see your personalised feed.
Every product is scored against the user's style vector using weighted matching:
style match → +40 pts
colour match → +30 pts
occasion match → +20 pts
size available → +10 pts
─────────────────────────
cart signal boost → +60 pts (contextual bandit, triggered on cart add)
Products are sorted by total score. Top 9 are rendered in the feed.
Builds a co-purchase graph across users. Users with overlapping purchase histories surface products the target user hasn't seen yet. Accessible via POST /api/recommend/collab.
Rule-based cross-category pairing:
topin cart → suggestsbottomonly (never top→top, never top→dress)bottomin cart → suggeststoponly- Filters by same gender
- Excludes items already in cart
Calls the Claude API with the user's full style profile as context. Answers are persona-specific, not templated. Accessible via POST /api/advisor.
| Method | Endpoint | Body | Returns |
|---|---|---|---|
GET |
/api/products |
— | All products |
GET |
/api/products/<id> |
— | Single product |
POST |
/api/recommend |
{profile, boosted_category?} |
Ranked products |
POST |
/api/recommend/collab |
{user_id} |
Collaborative suggestions |
POST |
/api/recommend/complements |
{product_id, user_id, exclude_ids} |
Outfit pairings |
POST |
/api/advisor |
{user_id, product_id, question} |
AI style advice |
GET |
/api/users |
— | All users |
| Sneha | Priya | |
|---|---|---|
| Style | Casual | Formal |
| Colour | Earth tones | Monochrome |
| Occasion | Daily wear | Work |
| Size | M | S |
| Purchase history | 2 past orders | None |
Switch between personas using the toggle in the top navigation bar to see how the same product catalog produces completely different ranked feeds.
| Criteria | Implementation |
|---|---|
| Context-Aware Personalisation | Style vector built in 30 sec via quiz; contextual bandit boosts categories on cart add |
| Cross-Platform Consistency | React SPA, fully responsive, consistent state across all views |
| Ethical Data Usage | Privacy Modal with per-signal toggles and one-click data erasure |
| Real-Time Adaptability | Feed re-ranks on every cart add, persona switch, and filter interaction |
| Measurable Impact | Two live personas with demonstrably different feeds; repeat-buy detection |
| Layer | Technology |
|---|---|
| Frontend | React 18 + Vite |
| Styling | CSS Custom Properties (no framework) |
| State Management | React hooks — centralised in App.jsx |
| API Client | Native fetch + Vite proxy |
| Backend | Python · Flask · Blueprints |
| Recommendation | Custom weighted scoring algorithm |
| AI Advisor | Claude API (Anthropic) |
| Data | JSON flat files (swappable for any database) |
The frontend includes a full client-side fallback. If the Flask server is not running:
- Products load from
src/data/products.js - Recommendations are scored in-browser using the same weighted algorithm
- AI Style Advisor shows a pre-written persona-specific response
- All UI features remain functional
- Image overflow bug — The original single-file frontend had no
overflow: hiddenon product image containers, causing images to bleed outside their cards (shoe image appearing above kurta cards). Fixed withoverflow: hidden+object-fit: cover+object-position: top centeron all image containers. - Single file → component architecture — Rebuilt from a 1,800-line
index.htmlinto a proper React component tree with separated concerns, testable hooks, and centralised state. - CORS / hardcoded URLs — Replaced all
localhost:5001direct calls with Vite proxy configuration.
StyleSense · Problem Statement 2 · Personalised Experiences at Scale