# Project export: Thread

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2026
- Tagline: Shopping reimagined. Thread is a AI-powered fashion platform that lets you search, discover, and virtually try on clothes using your own photo.
- Devpost: https://devpost.com/software/thread-6jx04m
- GitHub: http://github.com/arjanssuri/thread
- Video: https://www.youtube.com/embed/vc_zIQ9laHU?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — Arjan Suri (14 commits), Claude Opus 4.6 (13 commits), Adarsh Ashok (3 commits), Cursor (1 commits)

## Devpost submission (written by the team)

### Overview

One-liner: An AI-powered fashion platform that lets you search, discover, and virtually try on clothes using your own photo — generating personalized video try-ons with Google Veo 3.1.

### Inspiration

Online shopping is broken. You scroll through hundreds of flat product images, guess how something might look on you, order it, and return half of it. We wanted to build the future of fashion e-commerce — one where AI closes the gap between browsing and trying on. What if you could see yourself wearing any garment before you buy it? What if a personal shopping agent knew your style, your body, and your budget, and could find exactly what you're looking for in seconds? Thread was born from the frustration of returns, size charts, and the disconnect between how clothes look on a model versus on you.

### What it does

Thread is a full-stack AI fashion platform with four core experiences: AI Virtual Try-On — Upload your photo and select any product. Thread sends both your photo and the garment image as reference images to Google Veo 3.1, generating a personalized fashion video of you wearing the outfit. Gemini 2.5 Flash pre-analyzes both the product (fabric, fit, color, pattern) and your appearance (build, hair, skin tone, gender) to craft a detailed cinematic prompt. AI Virtual Try-On — Upload your photo and select any product. Thread sends both your photo and the garment image as reference images to Google Veo 3.1, generating a personalized fashion video of you wearing the outfit. Gemini 2.5 Flash pre-analyzes both the product (fabric, fit, color, pattern) and your appearance (build, hair, skin tone, gender) to craft a detailed cinematic prompt. 3D Body Model — An interactive mannequin built with mannequin-js and Three.js, calibrated to your body measurements (height, weight, gender, fit preference). Drag to rotate, scroll to zoom. The mannequin recolors to match the selected garment's dominant color, extracted via AI with a pixel-sampling fallback. 3D Body Model — An interactive mannequin built with mannequin-js and Three.js, calibrated to your body measurements (height, weight, gender, fit preference). Drag to rotate, scroll to zoom. The mannequin recolors to match the selected garment's dominant color, extracted via AI with a pixel-sampling fallback. AI Shopping Agent (Thread Bot) — A conversational shopping assistant powered by Gemini 2.0 Flash with tool-calling. It searches the catalog semantically, recommends products based on your style preferences and feedback, and refines results across multiple rounds. The bento grid UI shows activity, product tiles with like/pass buttons, and a liked items strip. AI Shopping Agent (Thread Bot) — A conversational shopping assistant powered by Gemini 2.0 Flash with tool-calling. It searches the catalog semantically, recommends products based on your style preferences and feedback, and refines results across multiple rounds. The bento grid UI shows activity, product tiles with like/pass buttons, and a liked items strip. Semantic Search — Natural language product search powered by Elasticsearch kNN with vector embeddings. Search "cozy oversized sweater for fall" and get ranked results by semantic similarity, not just keyword matching. Includes a 3D product graph visualization where search results light up within the full catalog. Semantic Search — Natural language product search powered by Elasticsearch kNN with vector embeddings. Search "cozy oversized sweater for fall" and get ranked results by semantic similarity, not just keyword matching. Includes a 3D product graph visualization where search results light up within the full catalog.

### How we built it

Frontend: Next.js 16 (App Router) with React 19, Tailwind CSS 4, Radix UI primitives, and shadcn/ui components. Deployed on Vercel. Backend & Data: Supabase — PostgreSQL database for products, user preferences, try-on history, and agent feedback. Supabase Auth for authentication. Supabase Storage for user photos and generated try-on videos. Elasticsearch — Vector search engine with kNN index for semantic product search. Embeddings generated via Elasticsearch's built-in inference API. Product scraper — Custom TypeScript scraper that pulls real product data from Shopify stores (Kith, Everlane, Gymshark, Allbirds, Fashion Nova, and more) via their public JSON APIs. AI/ML Stack: Google Gemini 2.5 Flash — Product image analysis (garment type, fabric, color, fit, pattern, features) and person photo analysis (build, hair, age, skin tone, gender). Structured JSON output. Google Gemini 2.0 Flash — Powers the shopping agent with function-calling for catalog search and multi-round recommendation refinement. Google Veo 3.1 Fast — Video generation with dual reference images (user photo + product image as ASSET references) for personalized try-on videos. sharp + heic-convert — Server-side image processing for photo uploads, including HEIC/HEIF conversion for iOS photos. 3D: mannequin-js for parametric body models, Three.js OrbitControls for interactive manipulation, React Three Fiber for rendering.

### Challenges we ran into

Veo reference images — Getting Veo to generate videos that actually look like the user required passing both the person's photo and the product image as ASSET reference images, plus crafting detailed prompts with AI-extracted appearance attributes. Text-only descriptions produced generic models. Veo reference images — Getting Veo to generate videos that actually look like the user required passing both the person's photo and the product image as ASSET reference images, plus crafting detailed prompts with AI-extracted appearance attributes. Text-only descriptions produced generic models. HEIC photo uploads — iOS users upload HEIC photos by default, but sharp doesn't ship with HEIC codec support. We had to add heic-convert as a pure-JS preprocessing step that detects HEIC files by extension, MIME type, and magic bytes before converting to JPEG. HEIC photo uploads — iOS users upload HEIC photos by default, but sharp doesn't ship with HEIC codec support. We had to add heic-convert as a pure-JS preprocessing step that detects HEIC files by extension, MIME type, and magic bytes before converting to JPEG. Vercel serverless limits — Video generation returns 5-20MB of video data, exceeding Vercel's ~4.5MB response body limit. We pivoted to uploading generated videos to Supabase Storage and returning the public URL instead. Also hit function timeout limits (10s default) and needed maxDuration on multiple routes. Vercel serverless limits — Video generation returns 5-20MB of video data, exceeding Vercel's ~4.5MB response body limit. We pivoted to uploading generated videos to Supabase Storage and returning the public URL instead. Also hit function timeout limits (10s default) and needed maxDuration on multiple routes. Mannequin interactivity — mannequin-js creates its own Three.js renderer and scene internally. Since we extract the canvas and manage it ourselves, the built-in controls weren't initialized. We had to create our own OrbitControls and hook into mannequin-js's animationLoop callback for per-frame updates. Mannequin interactivity — mannequin-js creates its own Three.js renderer and scene internally. Since we extract the canvas and manage it ourselves, the built-in controls weren't initialized. We had to create our own OrbitControls and hook into mannequin-js's animationLoop callback for per-frame updates. Semantic search quality — Getting vector search to return relevant results required tuning the embedding pipeline, implementing relevance score cutoffs, and building a sync layer between Supabase (source of truth) and Elasticsearch (search index). Semantic search quality — Getting vector search to return relevant results required tuning the embedding pipeline, implementing relevance score cutoffs, and building a sync layer between Supabase (source of truth) and Elasticsearch (search index).

### Accomplishments we're proud of

True personalized try-on — Not just "here's a generic model wearing the shirt." Thread uses your actual photo as a reference image, so the generated video depicts your face, your body, your hair. Combined with AI-extracted attributes and gender, the results feel personal. True personalized try-on — Not just "here's a generic model wearing the shirt." Thread uses your actual photo as a reference image, so the generated video depicts your face, your body, your hair. Combined with AI-extracted attributes and gender, the results feel personal. End-to-end AI pipeline — From product scraping to embedding generation to semantic search to AI analysis to video generation, every step is automated and connected. Select a product, and the system analyzes it, builds your body model, and generates a cinematic try-on video. End-to-end AI pipeline — From product scraping to embedding generation to semantic search to AI analysis to video generation, every step is automated and connected. Select a product, and the system analyzes it, builds your body model, and generates a cinematic try-on video. The shopping agent — A multi-round conversational agent that actually understands fashion context. It searches semantically, respects your preferences, learns from like/dislike feedback across rounds, and surfaces increasingly relevant recommendations. The shopping agent — A multi-round conversational agent that actually understands fashion context. It searches semantically, respects your preferences, learns from like/dislike feedback across rounds, and surfaces increasingly relevant recommendations. Real product data — Not mock data. Thread scrapes real products from real fashion brands, with real images, real prices, and real descriptions. Real product data — Not mock data. Thread scrapes real products from real fashion brands, with real images, real prices, and real descriptions.

### What we learned

Veo 3.1's reference image feature is powerful but requires careful prompt engineering to maintain character consistency — the AI-extracted appearance description combined with the photo reference produces significantly better results than either alone. Veo 3.1's reference image feature is powerful but requires careful prompt engineering to maintain character consistency — the AI-extracted appearance description combined with the photo reference produces significantly better results than either alone. Elasticsearch's built-in inference API makes vector search surprisingly accessible — you don't need a separate embedding service or model hosting. Elasticsearch's built-in inference API makes vector search surprisingly accessible — you don't need a separate embedding service or model hosting. Building for serverless (Vercel) forces good architectural decisions: streaming responses, offloading large payloads to object storage, and keeping function execution times bounded. Building for serverless (Vercel) forces good architectural decisions: streaming responses, offloading large payloads to object storage, and keeping function execution times bounded. The gap between "AI can do this" and "AI does this reliably in production" is significant. Every AI feature needed fallback paths, error handling, and graceful degradation. The gap between "AI can do this" and "AI does this reliably in production" is significant. Every AI feature needed fallback paths, error handling, and graceful degradation.

### What's next

Real-time virtual try-on — Using Veo's image-to-video with webcam frames for live try-on, instead of pre-recorded video generation. Outfit builder — Combine multiple products (top + bottom + shoes) into a single styled outfit with a unified try-on video. Social features — Share try-on videos, save outfits, get feedback from friends. Size recommendation — Use body measurements and garment analysis to predict the best size, reducing returns. More brands — Expand the product catalog with more scrapers and brand partnerships. Fine-tuned style model — Train on user feedback data to build a personalized style profile that improves recommendations over time.

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 139 recognized source files, 614 KB.
- CSS (language) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Supabase (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code
- Vercel (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository; commit authorship or trailers
- AI coding agent: Cursor — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (120 of 154)

```
.DS_Store
.gitignore
CLAUDE.md
frontend/.DS_Store
frontend/app/(auth)/layout.tsx
frontend/app/(auth)/login/page.tsx
frontend/app/(auth)/signup/page.tsx
frontend/app/agent/page.tsx
frontend/app/api/agent/feedback/route.ts
frontend/app/api/agent/route.ts
frontend/app/api/preferences/photo/route.ts
frontend/app/api/preferences/route.ts
frontend/app/api/products/graph/route.ts
frontend/app/api/products/route.ts
frontend/app/api/search/backfill-embeddings/route.ts
frontend/app/api/search/health/route.ts
frontend/app/api/search/index/route.ts
frontend/app/api/search/route.ts
frontend/app/api/tryon/analyze/route.ts
frontend/app/api/tryon/history/route.ts
frontend/app/api/tryon/route.ts
frontend/app/api/tryon/video/route.ts
frontend/app/auth/callback/route.ts
frontend/app/cart/page.tsx
frontend/app/collections/page.tsx
frontend/app/globals.css
frontend/app/layout.tsx
frontend/app/outfit/page.tsx
frontend/app/page.tsx
frontend/app/preferences/page.tsx
frontend/app/search/layout.tsx
frontend/app/search/page.tsx
frontend/components.json
frontend/components/agent-chat-widget.tsx
frontend/components/agent/.gitkeep
frontend/components/fade-image.tsx
frontend/components/graph/.gitkeep
frontend/components/header.tsx
frontend/components/mannequin-viewer.tsx
frontend/components/outfit/.gitkeep
frontend/components/outfit/product-card.tsx
frontend/components/outfit/product-grid.tsx
frontend/components/outfit/try-on-panel.tsx
frontend/components/preference-mannequin.tsx
frontend/components/search-modal.tsx
frontend/components/search/product-graph.tsx
frontend/components/sections/collection-section.tsx
frontend/components/sections/editorial-section.tsx
frontend/components/sections/featured-products-section.tsx
frontend/components/sections/footer-section.tsx
frontend/components/sections/gallery-section.tsx
frontend/components/sections/hero-section.tsx
frontend/components/sections/mannequin-section.tsx
frontend/components/sections/philosophy-section.tsx
frontend/components/sections/technology-section.tsx
frontend/components/sections/testimonials-section.tsx
frontend/components/theme-provider.tsx
frontend/components/ui/accordion.tsx
frontend/components/ui/alert-dialog.tsx
frontend/components/ui/alert.tsx
frontend/components/ui/aspect-ratio.tsx
frontend/components/ui/avatar.tsx
frontend/components/ui/badge.tsx
frontend/components/ui/breadcrumb.tsx
frontend/components/ui/button-group.tsx
frontend/components/ui/button.tsx
frontend/components/ui/calendar.tsx
frontend/components/ui/card.tsx
frontend/components/ui/carousel.tsx
frontend/components/ui/chart.tsx
frontend/components/ui/checkbox.tsx
frontend/components/ui/collapsible.tsx
frontend/components/ui/command.tsx
frontend/components/ui/context-menu.tsx
frontend/components/ui/dialog.tsx
frontend/components/ui/drawer.tsx
frontend/components/ui/dropdown-menu.tsx
frontend/components/ui/empty.tsx
frontend/components/ui/field.tsx
frontend/components/ui/form.tsx
frontend/components/ui/hover-card.tsx
frontend/components/ui/input-group.tsx
frontend/components/ui/input-otp.tsx
frontend/components/ui/input.tsx
frontend/components/ui/item.tsx
frontend/components/ui/kbd.tsx
frontend/components/ui/label.tsx
frontend/components/ui/menubar.tsx
frontend/components/ui/navigation-menu.tsx
frontend/components/ui/pagination.tsx
frontend/components/ui/popover.tsx
frontend/components/ui/progress.tsx
frontend/components/ui/radio-group.tsx
frontend/components/ui/resizable.tsx
frontend/components/ui/scroll-area.tsx
frontend/components/ui/select.tsx
frontend/components/ui/separator.tsx
frontend/components/ui/sheet.tsx
frontend/components/ui/sidebar.tsx
frontend/components/ui/skeleton.tsx
frontend/components/ui/slider.tsx
frontend/components/ui/sonner.tsx
frontend/components/ui/spinner.tsx
frontend/components/ui/switch.tsx
frontend/components/ui/table.tsx
frontend/components/ui/tabs.tsx
frontend/components/ui/textarea.tsx
frontend/components/ui/toast.tsx
frontend/components/ui/toaster.tsx
frontend/components/ui/toggle-group.tsx
frontend/components/ui/toggle.tsx
frontend/components/ui/tooltip.tsx
frontend/components/ui/use-mobile.tsx
frontend/components/ui/use-toast.ts
frontend/docs/elasticsearch-inference-setup.md
frontend/docs/testing-phase-2.md
frontend/hooks/use-mobile.ts
frontend/hooks/use-toast.ts
frontend/lib/agent/.gitkeep
frontend/lib/agent/run-agent.ts
[34 more files omitted for size]
```

### Dependencies

- frontend/package.json: @elastic/elasticsearch@^9.3.1, @google/genai@^1.41.0, @hookform/resolvers@^3.10.0, @radix-ui/react-accordion@1.2.2, @radix-ui/react-alert-dialog@1.1.4, @radix-ui/react-aspect-ratio@1.1.1, @radix-ui/react-avatar@1.1.2, @radix-ui/react-checkbox@1.1.3, @radix-ui/react-collapsible@1.1.2, @radix-ui/react-context-menu@2.2.4, @radix-ui/react-dialog@1.1.4, @radix-ui/react-dropdown-menu@2.1.4, @radix-ui/react-hover-card@1.1.4, @radix-ui/react-label@2.1.1, @radix-ui/react-menubar@1.1.4, @radix-ui/react-navigation-menu@1.2.3, @radix-ui/react-popover@1.1.4, @radix-ui/react-progress@1.1.1, @radix-ui/react-radio-group@1.2.2, @radix-ui/react-scroll-area@1.2.2, @radix-ui/react-select@2.1.4, @radix-ui/react-separator@1.1.1, @radix-ui/react-slider@1.2.2, @radix-ui/react-slot@1.1.1, @radix-ui/react-switch@1.1.2, @radix-ui/react-tabs@1.1.2, @radix-ui/react-toast@1.2.4, @radix-ui/react-toggle@1.1.1, @radix-ui/react-toggle-group@1.1.1, @radix-ui/react-tooltip@1.1.6, @react-three/drei@^10.7.7, @react-three/fiber@^9.5.0, @supabase/ssr@^0.8.0, @supabase/supabase-js@^2.95.3, @tailwindcss/postcss@^4.1.9, @types/node@^22, @types/react@^19, @types/react-dom@^19, @types/three@^0.182.0, @vercel/analytics@1.3.1, autoprefixer@^10.4.20, class-variance-authority@^0.7.1, clsx@^2.1.1, cmdk@1.0.4, date-fns@4.1.0, embla-carousel-react@8.5.1, heic-convert@^2.1.0, input-otp@1.4.1, lucide-react@^0.454.0, mannequin-js@^5.2.3, next@16.0.10, next-themes@^0.4.6, openai@^6.22.0, postcss@^8.5, react@19.2.0, react-day-picker@9.8.0, react-dom@19.2.0, react-hook-form@^7.60.0, react-resizable-panels@^2.1.7, recharts@2.15.4, sonner@^1.7.4, tailwind-merge@^3.3.1, tailwindcss@^4.1.9, tailwindcss-animate@^1.0.7, three@^0.182.0, tw-animate-css@1.3.3, typescript@^5, vaul@^1.1.2, zod@3.25.76
- scripts/package.json: @supabase/supabase-js@^2.95.3, dotenv@^16.4.7, tsx@^4.19.0

### Recent commits (newest first)

- Fix: image and referenceImages are mutually exclusive in Veo
- Fix framing: ensure face/head never cut off, add padding above head
- Use image-to-video for person photo, product as reference image only
- Clarify Veo prompt: reference image 1 is the person, image 2 is the garment
- Use veo-3.1-generate-preview for reference images (fast model ignores them)
- Add hackathon submission overview
- Pass both product image and user photo as Veo reference images
- Pass user photo as Veo reference image, add gender to prompt, bento grid agent page, HEIC support, Vercel compat
- bright data
- fix colors and jina embeddings
- Use Gemini AI for product color detection, fix mannequin clothing via native recolor API
- agent added
- Fix mannequin clothing application timing and video display cropping
- frontend & limits
- Lazy AI analysis, sharp color extraction, mannequin outfit, AI tags
- Gemini image analysis for Veo prompts, switch to veo-3.1-fast
- Include brand and category in semantic search embeddings
- Try-on history with Supabase Storage, history dropdown, bento grid fixes
- Graph spin animation, auto-generate from try-on, bento grid outfit layout
- Search bar open from header, default pants filter, install openai/elasticsearch deps

## Key source files (fetched from GitHub, selected and truncated for size)

### OVERVIEW.md

```markdown
# Thread

**One-liner:** An AI-powered fashion platform that lets you search, discover, and virtually try on clothes using your own photo — generating personalized video try-ons with Google Veo 3.1.

---

## Inspiration

Online shopping is broken. You scroll through hundreds of flat product images, guess how something might look on you, order it, and return half of it. We wanted to build the future of fashion e-commerce — one where AI closes the gap between browsing and trying on. What if you could see *yourself* wearing any garment before you buy it? What if a personal shopping agent knew your style, your body, and your budget, and could find exactly what you're looking for in seconds?

Thread was born from the frustration of returns, size charts, and the disconnect between how clothes look on a model versus on you.

## What it does

Thread is a full-stack AI fashion platform with four core experiences:

- **AI Virtual Try-On** — Upload your photo and select any product. Thread sends both your photo and the garment image as reference images to Google Veo 3.1, generating a personalized fashion video of *you* wearing the outfit. Gemini 2.5 Flash pre-analyzes both the product (fabric, fit, color, pattern) and your appearance (build, hair, skin tone, gender) to craft a detailed cinematic prompt.

- **3D Body Model** — An interactive mannequin built with mannequin-js and Three.js, calibrated to your body measurements (height, weight, gender, fit preference). Drag to rotate, scroll to zoom. The mannequin recolors to match the selected garment's dominant color, extracted via AI with a pixel-sampling fallback.

- **AI Shopping Agent (Thread Bot)** — A conversational shopping assistant powered by Gemini 2.0 Flash with tool-calling. It searches the catalog semantically, recommends products based on your style preferences and feedback, and refines results across multiple rounds. The bento grid UI shows activity, product tiles with like/pass buttons, and a liked items strip.

- **Semantic Search** — Natural language product search powered by Elasticsearch kNN with vector embeddings. Search "cozy oversized sweater for fall" and get ranked results by semantic similarity, not just keyword matching. Includes a 3D product graph visualization where search results light up within the full catalog.

## How we built it

**Frontend:** Next.js 16 (App Router) with React 19, Tailwind CSS 4, Radix UI primitives, and shadcn/ui components. Deployed on Vercel.

**Backend & Data:**
- **Supabase** — PostgreSQL database for products, user preferences, try-on history, and agent feedback. Supabase Auth for authentication. Supabase Storage for user photos and generated try-on videos.
- **Elasticsearch** — Vector search engine with kNN index for semantic product search. Embeddings generated via Elasticsearch's built-in inference API.
- **Product scraper** — Custom TypeScript scraper that pulls real product data from Shopify stores (Kith, Everlane, Gymshark, Allbirds, Fashion Nova
[truncated — 4822 more characters]
```

### CLAUDE.md

```markdown
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**thread** — a reimagined shopping experience built on semantic search and 3D visualization. Users search for products (e.g., "jeans") and explore results as an interactive 3D force-directed graph of clusters and items. Users can filter, scroll, and navigate within the graph. After finding items, they can visualize outfits on themselves using Three.js and Sora. An AI shopping agent can be spun up with user preferences to autonomously shop on their behalf.

## Tech Stack

- **Framework:** Next.js (App Router) with TypeScript
- **Package Manager:** pnpm
- **Database & Auth:** Supabase (Postgres + pgvector for semantic search, Auth, Edge Functions)
- **3D Visualization:** Three.js / React Three Fiber (R3F) for graph visualization and outfit rendering
- **AI/ML:** OpenAI embeddings for semantic search, Sora for outfit try-on generation
- **Styling:** TBD (Tailwind CSS recommended)

## Common Commands

```bash
pnpm dev          # Start dev server
pnpm build        # Production build
pnpm start        # Start production server
pnpm lint         # Run ESLint
pnpm type-check   # Run TypeScript compiler check (tsc --noEmit)
```

## Architecture

### Core Features

1. **Semantic Search** — Product queries are embedded via OpenAI and matched against pgvector embeddings in Supabase. Results are clustered by similarity.
2. **3D Graph Visualization** — Search results render as a force-directed graph using React Three Fiber. Clusters group related products; nodes are interactive and filterable.
3. **Outfit Visualization** — Selected items are composed into an outfit preview using Three.js. Sora generates a try-on image/video of the user wearing the outfit.
4. **AI Shopping Agent** — Users provide preferences (style, budget, sizing) and an autonomous agent browses, filters, and recommends products on their behalf.

### Planned Directory Structure

```
src/
├── app/                  # Next.js App Router pages and layouts
│   ├── (auth)/           # Auth-related routes (login, signup)
│   ├── search/           # Search results + graph view
│   ├── outfit/           # Outfit visualization / try-on
│   ├── agent/            # AI shopping agent dashboard
│   └── api/              # API route handlers
├── components/
│   ├── graph/            # 3D graph components (R3F Canvas, nodes, edges, clusters)
│   ├── outfit/           # Three.js outfit viewer, Sora try-on
│   ├── agent/            # Agent UI (preferences form, activity feed)
│   └── ui/               # Shared UI primitives
├── lib/
│   ├── supabase/         # Supabase client, server client, middleware helpers
│   ├── embeddings/       # OpenAI embedding generation and vector search
│   ├── agent/            # AI agent logic (tool definitions, preference engine)
│   └── utils/            # Shared utilities
├── types/                # Shared TypeScript types and interfaces
└──
[truncated — 6326 more characters]
```

### scripts/package.json

```
{
  "name": "thread-scripts",
  "private": true,
  "type": "module",
  "scripts": {
    "scrape": "tsx scrape.ts"
  },
  "dependencies": {
    "@supabase/supabase-js": "^2.95.3",
    "dotenv": "^16.4.7",
    "tsx": "^4.19.0"
  }
}

```

### frontend/package.json

```
{
  "name": "my-v0-project",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "build": "next build",
    "dev": "next dev",
    "lint": "eslint .",
    "start": "next start",
    "type-check": "tsc --noEmit"
  },
  "dependencies": {
    "@elastic/elasticsearch": "^9.3.1",
    "@google/genai": "^1.41.0",
    "@hookform/resolvers": "^3.10.0",
    "@radix-ui/react-accordion": "1.2.2",
    "@radix-ui/react-alert-dialog": "1.1.4",
    "@radix-ui/react-aspect-ratio": "1.1.1",
    "@radix-ui/react-avatar": "1.1.2",
    "@radix-ui/react-checkbox": "1.1.3",
    "@radix-ui/react-collapsible": "1.1.2",
    "@radix-ui/react-context-menu": "2.2.4",
    "@radix-ui/react-dialog": "1.1.4",
    "@radix-ui/react-dropdown-menu": "2.1.4",
    "@radix-ui/react-hover-card": "1.1.4",
    "@radix-ui/react-label": "2.1.1",
    "@radix-ui/react-menubar": "1.1.4",
    "@radix-ui/react-navigation-menu": "1.2.3",
    "@radix-ui/react-popover": "1.1.4",
    "@radix-ui/react-progress": "1.1.1",
    "@radix-ui/react-radio-group": "1.2.2",
    "@radix-ui/react-scroll-area": "1.2.2",
    "@radix-ui/react-select": "2.1.4",
    "@radix-ui/react-separator": "1.1.1",
    "@radix-ui/react-slider": "1.2.2",
    "@radix-ui/react-slot": "1.1.1",
    "@radix-ui/react-switch": "1.1.2",
    "@radix-ui/react-tabs": "1.1.2",
    "@radix-ui/react-toast": "1.2.4",
    "@radix-ui/react-toggle": "1.1.1",
    "@radix-ui/react-toggle-group": "1.1.1",
    "@radix-ui/react-tooltip": "1.1.6",
    "@react-three/drei": "^10.7.7",
    "@react-three/fiber": "^9.5.0",
    "@supabase/ssr": "^0.8.0",
    "@supabase/supabase-js": "^2.95.3",
    "@vercel/analytics": "1.3.1",
    "autoprefixer": "^10.4.20",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "1.0.4",
    "date-fns": "4.1.0",
    "embla-carousel-react": "8.5.1",
    "heic-convert": "^2.1.0",
    "input-otp": "1.4.1",
    "lucide-react": "^0.454.0",
    "mannequin-js": "^5.2.3",
    "next": "16.0.10",
    "next-themes": "^0.4.6",
    "openai": "^6.22.0",
    "react": "19.2.0",
    "react-day-picker": "9.8.0",
    "react-dom": "19.2.0",
    "react-hook-form": "^7.60.0",
    "react-resizable-panels": "^2.1.7",
    "recharts": "2.15.4",
    "sonner": "^1.7.4",
    "tailwind-merge": "^3.3.1",
    "tailwindcss-animate": "^1.0.7",
    "three": "^0.182.0",
    "vaul": "^1.1.2",
    "zod": "3.25.76"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4.1.9",
    "@types/node": "^22",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "@types/three": "^0.182.0",
    "postcss": "^8.5",
    "tailwindcss": "^4.1.9",
    "tw-animate-css": "1.3.3",
    "typescript": "^5"
  }
}

```

### frontend/app/page.tsx

```typescript
import { Header } from "@/components/header";
import { HeroSection } from "@/components/sections/hero-section";
import { PhilosophySection } from "@/components/sections/philosophy-section";
import { TechnologySection } from "@/components/sections/technology-section";
import { MannequinSection } from "@/components/sections/mannequin-section";

export default function Home() {
  return (
    <main className="min-h-screen bg-background">
      <Header />
      <HeroSection />
      <PhilosophySection />
      <TechnologySection />
      <MannequinSection />
    </main>
  );
}

```

### frontend/app/layout.tsx

```typescript
import React from "react"
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { Analytics } from '@vercel/analytics/next'
import { CartProvider } from '@/lib/cart-context'
import './globals.css'

const inter = Inter({ subsets: ["latin"], variable: '--font-inter' });

export const metadata: Metadata = {
  title: 'thread',
  description: 'Shopping reimagined. Semantic search, 3D visualization, AI-powered outfit try-on, and your own personal shopping agent.',
  icons: {
    icon: '/favicon.svg',
  },
}

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="en" className="dark" suppressHydrationWarning>
      <body className={`${inter.variable} font-sans antialiased`} suppressHydrationWarning>
        <CartProvider>
          {children}
        </CartProvider>
        <Analytics />
      </body>
    </html>
  )
}

```

### frontend/app/search/layout.tsx

```typescript
import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "Search | thread",
  description: "Semantic search over products",
};

export default function SearchLayout({
  children,
}: { children: React.ReactNode }) {
  return children;
}

```

### frontend/app/(auth)/layout.tsx

```typescript
import type { Metadata } from "next";
import { Header } from "@/components/header";

export const metadata: Metadata = {
  title: "Sign in | thread",
  description: "Sign in or create an account",
};

export default function AuthLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="relative min-h-screen bg-foreground">
      <Header />
      {/* Background image */}
      <div
        className="absolute inset-0 bg-cover bg-center opacity-30"
        style={{
          backgroundImage:
            "url(https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=1920&h=1080&fit=crop)",
        }}
      />
      <div className="absolute inset-0 bg-gradient-to-b from-black/60 via-black/40 to-black/80" />
      <div className="relative flex min-h-screen flex-col items-center justify-center px-4 pt-24 pb-12">
        <div className="w-full max-w-lg rounded-2xl bg-white/15 backdrop-blur-xl border border-white/30 p-10">
          {children}
        </div>
      </div>
    </div>
  );
}

```

### frontend/app/collections/page.tsx

```typescript
"use client";

import { useState } from "react";
import { Header } from "@/components/header";
import { ProductGrid } from "@/components/outfit/product-grid";
import { TryOnPanel } from "@/components/outfit/try-on-panel";
import type { Product } from "@/types/product";

export default function CollectionsPage() {
  const [selectedProduct, setSelectedProduct] = useState<Product | null>(null);

  return (
    <main className="min-h-screen bg-background">
      <Header />
      <div className="pt-28" />

      <div className="mx-auto max-w-7xl px-6 md:px-12">
        <h1 className="text-4xl font-bold tracking-tight text-foreground md:text-5xl">
          Collections
        </h1>
        <p className="mt-2 text-lg text-muted-foreground">
          Browse and shop all pieces.
        </p>
      </div>

      <div className="mx-auto max-w-7xl px-6 py-8 md:px-12">
        <ProductGrid
          onSelect={setSelectedProduct}
          selectedId={selectedProduct?.id}
        />
      </div>

      {selectedProduct && (
        <TryOnPanel
          product={selectedProduct}
          onClose={() => setSelectedProduct(null)}
        />
      )}
    </main>
  );
}

```

### frontend/lib/supabase/server.ts

```typescript
import { createServerClient } from "@supabase/ssr";
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
import { cookies } from "next/headers";

export async function createClient() {
  const cookieStore = await cookies();

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll();
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            );
          } catch {
            // setAll called from a Server Component; middleware will refresh session
          }
        },
      },
    }
  );
}

/**
 * Service role client — use only in server-side routes that need to bypass RLS
 * (e.g. backfilling embeddings). Never expose to the client.
 */
export function createServiceRoleClient() {
  const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
  const key = process.env.SUPABASE_SERVICE_ROLE_KEY;
  if (!url || !key) throw new Error("SUPABASE_SERVICE_ROLE_KEY is not set");
  return createSupabaseClient(url, key);
}

```

[129 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]