# Project export: Artki.tech

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: Cal Hacks 12.0
- Tagline: AI-native interior design platform that learns your taste and generates personalized 3D room visualizations from products you could buy off of Amazon w/ recommendations.
- Devpost: https://devpost.com/software/artki-tech
- GitHub: https://github.com/MurtazaKafka/interior-design
- Demo: http://artki.tech/
- Video: https://www.youtube.com/embed/klPlCoSgnOA?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Result: winner (Chroma: Best AI application using Chroma)
- Team: 4 GitHub contributor(s) — Murtaza Nikzad (14 commits), Fawwaz Firdaus (7 commits), rishi-golla (6 commits), atckr (1 commits)

## Devpost submission (written by the team)

### Inspiration

The spark came during a late-night furniture shopping session. We watched a friend spend hours on Pinterest creating mood boards, then struggle to find matching furniture on multiple websites. Despite having great taste, they couldn't translate their vision into reality. We realized this was a universal problem: the gap between inspiration and implementation in interior design. Nearly 98% of design enthusiasts are dissatisfied with their home decor, yet over $25 billion is spent on interior design each year in the U.S. While AI had revolutionized many creative fields, interior design remained fragmented across inspiration platforms, furniture retailers, and 3D planning tools. Our breakthrough insight: what if we could learn someone's aesthetic preferences the same way Spotify learns musical taste - not through questionnaires, but through choices? Museum artworks became our "songs" - universally recognized pieces that reveal deep aesthetic preferences through simple A/B comparisons. What It Does Artki.tech is an AI-powered interior design platform that creates personalized 3D room visualizations with real, purchasable furniture based on your unique taste profile. Here's the complete flow: Floorplan Analysis: Users upload their room's floorplan, which gets transformed into a 3D room reconstruction using Claude-generated Three.js code. Floorplan Analysis: Users upload their room's floorplan, which gets transformed into a 3D room reconstruction using Claude-generated Three.js code. Taste Discovery: Users compare 12 pairs of museum artworks (Monet vs. Picasso, Van Gogh vs. Warhol). Each choice updates a 512-dimensional taste vector using CLIP embeddings, learning aesthetic preferences without questionnaires. Taste Discovery: Users compare 12 pairs of museum artworks (Monet vs. Picasso, Van Gogh vs. Warhol). Each choice updates a 512-dimensional taste vector using CLIP embeddings, learning aesthetic preferences without questionnaires. Real Product Discovery: Our system scrapes Amazon to find actual furniture products matching your taste profile, ensuring everything you see can be purchased. Real Product Discovery: Our system scrapes Amazon to find actual furniture products matching your taste profile, ensuring everything you see can be purchased. AI-Powered 3D Pipeline: Amazon products are enhanced with OpenAI-generated images Images are converted to 3D models using Claude's Three.js generation Models are rendered in your reconstructed room AI-Powered 3D Pipeline: Amazon products are enhanced with OpenAI-generated images Images are converted to 3D models using Claude's Three.js generation Models are rendered in your reconstructed room Interactive Visualization: Real-time Three.js rendering shows actual purchasable furniture in your specific room layout. Users can rotate, zoom, and rearrange items to perfect their design. Interactive Visualization: Real-time Three.js rendering shows actual purchasable furniture in your specific room layout. Users can rotate, zoom, and rearrange items to perfect their design. Smart Recommendations: ChromaDB's vector search finds semantically similar products based on visual features, style tags, and your evolving preferences. Smart Recommendations: ChromaDB's vector search finds semantically similar products based on visual features, style tags, and your evolving preferences. Architecture Overview Frontend: Next.js 16 + React 19 + TypeScript + Three.js + React Three Fiber Backend: FastAPI + Python 3.11 AI/ML: Claude 4.5 Sonnet + CLIP embeddings + OpenAI API + NeRF Database: ChromaDB Cloud for vectors 3D: Three.js + React Three Fiber + NeRF reconstruction Data Source: Amazon product scraping for real furniture Development Process & Technical Evolution Initial Approach: NeRF Neural Radiance Fields We started by training NeRF (Neural Radiance Fields) models to create photorealistic 3D reconstructions of rooms from just a few photos Built a Flask API server (api_server.py) to handle NeRF training with user-uploaded images Successfully generated 3D room reconstructions from 10+ photos per room Pivot Decision: While NeRF worked, the output had low fidelity and training took 8-10 minutes per room Day 1: Foundation & Pivot Set up Next.js frontend and FastAPI backend Integrated Three.js for 3D visualization Key Pivot: Switched from NeRF to Claude API for faster, higher-quality 3D generation Claude generates Three.js code directly, which we render with React Three Fiber Reduced generation time from 30 minutes to 3 seconds Day 2: AI Integration & Product Pipeline Implemented CLIP embeddings for artwork analysis Built taste vector algorithm for preference learning Amazon Integration: Created web scraping system to find real products matching user preferences Image-to-3D Pipeline: Scrape Amazon for furniture matching user taste Use OpenAI API to generate product images Convert images to 3D models using Claude Render models in Three.js scene Scrape Amazon for furniture matching user taste Use OpenAI API to generate product images Convert images to 3D models using Claude Render models in Three.js scene Day 3: Complete System Integration Connected floorplan upload to room reconstruction Integrated user preference embeddings with product search Built complete pipeline: Floorplan → Room Reconstruction → Preference Analysis → Amazon Scraping → Image Generation → 3D Conversion → Final Visualization Polished UI/UX with TailwindCSS Complete Technical Pipeline Room Reconstruction: User uploads floorplan → Claude generates Three.js room geometry from floorplan specifications Room Reconstruction: User uploads floorplan → Claude generates Three.js room geometry from floorplan specifications Taste Learning: CLIP encodes museum artworks into 512-dimensional vectors. User choices update their vector: user_vec = user_vec + win_vec - 0.5 * lose_vec Taste Learning: CLIP encodes museum artworks into 512-dimensional vectors. User choices update their vector: user_vec = user_vec + win_vec - 0.5 * lose_vec Product Discovery: Scrape Amazon for furniture matching taste vector Extract product metadata (price, dimensions, materials) Generate embeddings for semantic search Product Discovery: Scrape Amazon for furniture matching taste vector Extract product metadata (price, dimensions, materials) Generate embeddings for semantic search 3D Model Generation: OpenAI API transforms product descriptions into detailed images Images fed to Claude for Three.js code generation Real-time rendering of actual products as 3D models 3D Model Generation: OpenAI API transforms product descriptions into detailed images Images fed to Claude for Three.js code generation Real-time rendering of actual products as 3D models Final Visualization: Combine room reconstruction with generated furniture models in interactive 3D scene Final Visualization: Combine room reconstruction with generated furniture models in interactive 3D scene Challenges We Ran Into 1. NeRF Training Performance Problem: NeRF neural radiance field training took 15-30 minutes per room with low-fidelity output. Solution: Pivoted to Claude API for instant Three.js code generation, reducing time from 30 minutes to 3 seconds while improving quality. 2. Amazon Product Integration Problem: Connecting abstract taste preferences to real, purchasable products. Solution: Built web scraper for Amazon products, then used embeddings to match products to user taste vectors. 3. Image-to-3D Conversion Pipeline Problem: No direct way to convert Amazon product images to 3D models. Solution: Created multi-step pipeline: Amazon data → OpenAI image enhancement → Claude 3D code generation → Three.js rendering. 4. 3D Model Loading Issues Problem: GLTF files referenced external textures, causing 404 errors. Solution: Converted to self-contained GLB format with embedded textures. 5. Embedding Performance Problem: Generating CLIP embeddings for scraped products took 30+ seconds. Solution: Pre-computed embeddings stored in ChromaDB, reducing search to <100ms. 6. AI Code Generation Reliability Problem: Claude sometimes generated invalid Three.js code for complex furniture. Solution: Implemented robust error handling with fallback hand-crafted generators for common furniture types. 7. Floorplan to 3D Reconstruction Problem: Converting 2D floorplan images to accurate 3D room geometry. Solution: Used Claude to interpret floorplan and generate proportional Three.js room structures. Accomplishments That We're Proud Of Successfully Pivoted from NeRF: Started with neural radiance fields, recognized limitations, and pivoted to a better solution within 24 hours Successfully Pivoted from NeRF: Started with neural radiance fields, recognized limitations, and pivoted to a better solution within 24 hours End-to-End Pipeline: Built complete pipeline from floorplan upload to 3D room with real Amazon products - a truly functional prototype End-to-End Pipeline: Built complete pipeline from floorplan upload to 3D room with real Amazon products - a truly functional prototype Multi-AI Orchestration: Successfully integrated 5 different AI systems (Claude, CLIP, OpenAI, ChromaDB, NeRF) into one seamless experience Multi-AI Orchestration: Successfully integrated 5 different AI systems (Claude, CLIP, OpenAI, ChromaDB, NeRF) into one seamless experience Real Product Integration: Connected abstract preferences to actual purchasable Amazon products, solving a real-world problem Real Product Integration: Connected abstract preferences to actual purchasable Amazon products, solving a real-world problem Real-time 3D Generation: Reduced 3D generation from 30 minutes (NeRF) to 3 seconds (Claude) while improving quality Real-time 3D Generation: Reduced 3D generation from 30 minutes (NeRF) to 3 seconds (Claude) while improving quality Lightning-Fast Search: <100ms semantic search across scraped products with 512-dimensional vectors Lightning-Fast Search: <100ms semantic search across scraped products with 512-dimensional vectors Production-Ready Architecture: Built scalable, well-documented codebase that could be deployed tomorrow Production-Ready Architecture: Built scalable, well-documented codebase that could be deployed tomorrow What We Learned Technical Insights Multi-modal AI is powerful: Combining visual (CLIP) and language (Claude) AI creates emergent capabilities Vector databases are game-changers: ChromaDB enabled instant personalized search Prompt engineering matters: Structured prompts improved Claude's code generation by 70% Fallbacks are essential: Every AI component needs a reliable backup Product Insights Users want simplicity: 12 comparisons hit the sweet spot between accuracy and user patience Visual choices reveal preferences: People make faster, more confident decisions with images than questionnaires 3D visualization sells: Seeing furniture in context dramatically improves user confidence Team Insights API integration complexity: Coordinating multiple external APIs requires careful error handling Performance optimization is iterative: Each bottleneck revealed led to architectural improvements What's Next for Artki.tech Immediate Goals (Next Month) Real Furniture Integration: Partner with IKEA, Wayfair, West Elm for actual purchasable items Mobile AR Preview: Use ARKit/ARCore for in-room visualization Expand Catalog: 500+ furniture items with real product links Business Model Freemium: Free taste profiling + 3 room designs Pro Subscription: Unlimited designs, high-res exports, AR preview Affiliate Revenue: Commission from furniture purchases Enterprise API: White-label solution for furniture retailers

## README (from the GitHub repository)

# Interior Design 3D Furniture Search

AI-powered interior design assistant that uses semantic search to find and place 3D furniture models based on user preferences and natural language queries.

## 🏗️ Architecture

### Tech Stack
- **Frontend**: Next.js 16 + React 19 + Three.js (3D rendering)
- **Backend**: FastAPI + Python 3.10+
- **ML/AI**: 
  - CLIP (OpenAI) for image/text embeddings
  - Claude 3.5 Sonnet (Anthropic) for natural language query enhancement
- **Vector DB**: ChromaDB Cloud for semantic search
- **3D Models**: GLTF/OBJ formats

### How It Works

1. **User Preference Collection**: Users complete a style quiz (A/B testing with artwork images)
2. **Taste Embedding**: CLIP generates a 512-dimensional taste vector stored in ChromaDB
3. **Natural Language Queries**: Users describe furniture they want ("I need a cozy modern wooden coffee table")
4. **Query Enhancement (Claude)**: AI parses the query to extract:
   - Category (furniture/lighting/painting)
   - Subcategory (sofa/table/lamp)
   - Style tags (modern, scandinavian, etc.)
   - Materials (wood, metal, glass)
   - Colors and dimensions
5. **Hybrid Search**: Combines user preference vector (60%) + enhanced text query embedding (40%)
6. **3D Rendering**: Loads and places selected furniture models in the 3D room scene

## 📁 Project Structure

```
.
├── artspace-interior/artspace-ui/          # Frontend (Next.js)
│   ├── app/
│   │   ├── components/
│   │   │   ├── 3DViewer.tsx               # Three.js 3D scene
│   │   │   ├── FloorplanUploader.tsx       # Upload room floorplan
│   │   │   ├── StyleQuiz.tsx               # User taste preferences
│   │   │   └── StudioChatPanel.tsx         # Chat interface for queries
│   │   └── page.tsx                        # Main app flow
│   └── lib/
│       ├── furniture-api.ts                # API client for furniture search
│       └── nerf-api.ts                     # NeRF 3D reconstruction
│
└── taste-fingerprint/                      # Backend (Python)
    ├── apps/serve/
    │   ├── main.py                         # FastAPI server
    │   ├── services/
    │   │   ├── embeddings.py               # CLIP embedding utilities
    │   │   └── furniture.py                # Furniture search service
    │   └── scripts/
    │       └── embed_furniture.py          # Populate ChromaDB with furniture
    │
    └── packages/catalog/
        ├── furniture.json                  # Curated furniture catalog (22 items)
        └── artworks.json                   # Artwork catalog for taste quiz

```

## 🚀 Setup Instructions

### 1. Clone and Navigate

```bash
cd /path/to/interior-design
```

### 2. Backend Setup (taste-fingerprint)

```bash
cd taste-fingerprint/apps/serve

# Create virtual environment
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Create .env file with your own credentials
cat > .env << 'EOF'
CHROMA_API_KEY=<your_chroma_api_key>
CHROMA_TENANT=<your_chroma_tenant_id>
CHROMA_DATABASE=taste-fingerprint
ANTHROPIC_API_KEY=<your_anthropic_api_key>
SKETCHFAB_TOKEN=<your_sketchfab_token>
CORS_ALLOW_ORIGINS=http://localhost:3000,http://localhost:3001
EOF

# Embed furniture catalog into ChromaDB
python scripts/embed_furniture.py

# Start the API server
uvicorn main:app --reload --port 8000
```

The API will be available at `http://localhost:8000`

### 3. Frontend Setup (artspace-ui)

```bash
cd ../../artspace-interior/artspace-ui

# Install dependencies
npm install

# Create .env.local file
cat > .env.local << 'EOF'
NEXT_PUBLIC_API_BASE=http://localhost:8000
NEXT_PUBLIC_FURNITURE_API_URL=http://localhost:8000
NEXT_PUBLIC_NERF_API_URL=http://localhost:5000
EOF

# Start the development server
npm run dev
```

The app will be available at `http://localhost:3000`

## 🎯 Usage Flow

### 1. Upload Floorplan
- User uploads a room floorplan image
- System processes it to create 3D room geometry

### 2. Style Preferences
- User completes a style quiz (9 questions)
- System generates taste vector using CLIP embeddings
- Vector stored in ChromaDB under user_id

### 3. Search Furniture
- User enters natural language query: "modern wooden coffee table"
- System searches furniture catalog using hybrid approach:
  - User taste vector (60 weight)
  - Text query embedding (40% weight)
- Returns ranked results with similarity scores

### 4. 3D Visualization
- Selected furniture loaded into Three.js scene
- User can view, rotate, and explore the furnished room

## 🔌 API Endpoints

### Furniture Search

**POST** `/api/furniture/search`

```json
{
  "user_id": "user_123",
  "text_query": "I need a cozy modern wooden coffee table for my living room",
  "category": "furniture",
  "limit": 10,
  "use_claude": true
}
```

**Claude Enhancement Example:**
Input: "I need a cozy modern wooden coffee table"
Claude extracts:
```json
{
  "enhanced_text": "modern scandinavian oak coffee table",
  "category": "furniture",
  "subcategory": "table",
  "style_tags": ["modern", "scandinavian", "cozy"],
  "materials": ["wood", "oak"],
  "colors": ["natural"]
}
```

Response:
```json
{
  "items": [
    {
      "id": "furn_table_coffee_002",
      "name": "Round Wooden Coffee Table",
      "category": "furniture",
      "subcategory": "table",
      "styleTags": ["scandinavian", "natural", "organic"],
      "colors": ["oak", "natural", "wood"],
      "dimensions": { "width": 36, "depth": 36, "height": 16, "unit": "inches" },
      "description": "Round coffee table with solid oak top and splayed legs",
      "image_url": "/furniture/table_coffee_002.jpg",
      "model_url": "/models/furniture/table_coffee_002.glb",
      "model_format": "gltf",
      "similarity_score": 0.8234
    }
  ],
  "count": 1,
  "query": {
    "user_id": "user_123",
    "text_query": "modern wooden coffee table",
    "category": "furniture"
  }
}
```

### Get Furniture by ID

**GET** `/api/furniture/{furniture_id}`

### User Taste Update

**POST** `/taste/update`

```json
{
  "user_id": "user_123",
  "win_id": "art_botticelli_john",
  "lose_id": "art_caravaggio_denial"
}
```

## 📊 Furniture Catalog

The catalog contains 22 curated 3D furniture items:

- **Furniture** (14 items): Sofas, chairs, tables, bookshelves, rugs, plants, cushions
- **Lighting** (5 items): Floor lamps, table lamps, pendants, chandeliers  
- **Paintings** (4 items): Abstract, botanical, landscape artwork

Each item includes:
- Name, description, dimensions
- Style tags (modern, mid-century, scandinavian, etc.)
- Color palette
- Image URL (for embedding)
- 3D model URL (GLTF format)

### Adding More Items

1. Add new entries to `packages/catalog/furniture.json`
2. Add corresponding images to `apps/web/public/furniture/`
3. Add 3D models to `apps/web/public/models/`
4. Re-run the embedding script:

```bash
cd taste-fingerprint/apps/serve
python scripts/embed_furniture.py
```

## 🧪 Testing

### Test Backend API

```bash
# Health check
curl http://localhost:8000/health

# Search furniture
curl -X POST http://localhost:8000/api/furniture/search \
  -H "Content-Type: application/json" \
  -d '{
    "text_query": "modern sofa",
    "category": "furniture",
    "limit": 5
  }'
```

### Test Frontend

1. Navigate to `http://localhost:3000`
2. Upload a floorplan image
3. Complete the style quiz
4. View the 3D room with furniture

## 🔧 Troubleshooting

### ChromaDB Connection Issues
- Verify API key, tenant, and database name in `.env`
- Check network connectivity to ChromaDB Cloud

### Embedding Script Fails
- Ensure furniture images exist in `apps/web/public/furniture/`
- Check image paths in `furniture.json` match actual files
- Verify CLIP model downloads successfully

### 3D Models Not Loading
- Check model URLs in `furniture.json` are correct
- Verify GLTF files are valid (test with online viewer)
- Check browser console for Three.js errors

### CORS Errors
- Verify `CORS_ALLOW_ORIGINS` in backend `.env` includes frontend URL
- Check `NEXT_PUBLIC

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 88 recognized source files, 459 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- Hugging Face (technology) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- PyTorch (technology) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Flask (technology) — claimed on Devpost, not found in the code
- Vercel (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 121)

```
.gitignore
artspace-interior/artspace-ui/.gitignore
artspace-interior/artspace-ui/3D_MODELS_FINAL_STATUS.md
artspace-interior/artspace-ui/3D_MODELS_STATUS.md
artspace-interior/artspace-ui/api_server.py
artspace-interior/artspace-ui/app/components/3DViewer.tsx
artspace-interior/artspace-ui/app/components/ChatBadgeStrip.tsx
artspace-interior/artspace-ui/app/components/ChatComposer.tsx
artspace-interior/artspace-ui/app/components/ChatTranscript.tsx
artspace-interior/artspace-ui/app/components/Claude3DViewer.tsx
artspace-interior/artspace-ui/app/components/CompleteRoomGenerator.tsx
artspace-interior/artspace-ui/app/components/ConceptPreviewCard.tsx
artspace-interior/artspace-ui/app/components/CurationForm.tsx
artspace-interior/artspace-ui/app/components/FloorplanUploader.tsx
artspace-interior/artspace-ui/app/components/HeroCanvas.tsx
artspace-interior/artspace-ui/app/components/ImageTo3D.tsx
artspace-interior/artspace-ui/app/components/InspirationUploader.tsx
artspace-interior/artspace-ui/app/components/MeshPreview.tsx
artspace-interior/artspace-ui/app/components/PageBanner.tsx
artspace-interior/artspace-ui/app/components/PageTransition.tsx
artspace-interior/artspace-ui/app/components/ScrollArtwork.tsx
artspace-interior/artspace-ui/app/components/SectionCard.tsx
artspace-interior/artspace-ui/app/components/StepHeader.tsx
artspace-interior/artspace-ui/app/components/StudioChatPanel.tsx
artspace-interior/artspace-ui/app/components/StudioHeader.tsx
artspace-interior/artspace-ui/app/components/StudioStatusBar.tsx
artspace-interior/artspace-ui/app/components/StylePresetGrid.tsx
artspace-interior/artspace-ui/app/components/StyleQuiz.tsx
artspace-interior/artspace-ui/app/components/TasteFingerprint.tsx
artspace-interior/artspace-ui/app/components/ZoomScene.tsx
artspace-interior/artspace-ui/app/constants.ts
artspace-interior/artspace-ui/app/globals.css
artspace-interior/artspace-ui/app/layout.tsx
artspace-interior/artspace-ui/app/page.tsx
artspace-interior/artspace-ui/app/studio/page.tsx
artspace-interior/artspace-ui/app/types/chat.ts
artspace-interior/artspace-ui/app/utils/textareaResize.ts
artspace-interior/artspace-ui/assets/gaudi10.avif
artspace-interior/artspace-ui/eslint.config.mjs
artspace-interior/artspace-ui/lib/claude-3d-generator.ts
artspace-interior/artspace-ui/lib/furniture-api.ts
artspace-interior/artspace-ui/lib/nerf-api.ts
artspace-interior/artspace-ui/lib/room-generator.ts
artspace-interior/artspace-ui/lib/taste-api.ts
artspace-interior/artspace-ui/next.config.ts
artspace-interior/artspace-ui/package.json
artspace-interior/artspace-ui/postcss.config.mjs
artspace-interior/artspace-ui/public/models/furniture/avocado.glb
artspace-interior/artspace-ui/public/models/furniture/barramundi.glb
artspace-interior/artspace-ui/public/models/furniture/boom.glb
artspace-interior/artspace-ui/public/models/furniture/chair.glb
artspace-interior/artspace-ui/public/models/furniture/lamp.glb
artspace-interior/artspace-ui/public/models/furniture/sofa.glb
artspace-interior/artspace-ui/public/models/furniture/table.glb
artspace-interior/artspace-ui/public/models/lighting/light_ceiling_001.glb
artspace-interior/artspace-ui/public/models/lighting/light_floor_001.glb
artspace-interior/artspace-ui/public/models/lighting/light_floor_002.glb
artspace-interior/artspace-ui/public/models/lighting/light_table_001.glb
artspace-interior/artspace-ui/README.md
artspace-interior/artspace-ui/scripts/download_3d_models.py
artspace-interior/artspace-ui/TASTE_FINGERPRINT_INTEGRATION.md
artspace-interior/artspace-ui/tsconfig.json
artspace-interior/artspace-ui/types/three-examples.d.ts
artspace-interior/artspace-ui/vercel.json
DEMO_RUNBOOK.md
DEPLOYMENT.md
FURNITURE_SEARCH_README.md
IMPLEMENTATION_SUMMARY.md
README.md
render.yaml
setup-furniture-search.sh
simple_3d_test.html
taste-fingerprint/apps/__init__.py
taste-fingerprint/apps/serve/__init__.py
taste-fingerprint/apps/serve/main.py
taste-fingerprint/apps/serve/requirements.txt
taste-fingerprint/apps/serve/scripts/__init__.py
taste-fingerprint/apps/serve/scripts/clean_products.py
taste-fingerprint/apps/serve/scripts/download_product_images.py
taste-fingerprint/apps/serve/scripts/embed_artworks.py
taste-fingerprint/apps/serve/scripts/embed_furniture.py
taste-fingerprint/apps/serve/scripts/embed_products.py
taste-fingerprint/apps/serve/services/__init__.py
taste-fingerprint/apps/serve/services/claude_3d_generator.py
taste-fingerprint/apps/serve/services/claude.py
taste-fingerprint/apps/serve/services/complete_room_generator.py
taste-fingerprint/apps/serve/services/dataset_integrations.py
taste-fingerprint/apps/serve/services/embeddings.py
taste-fingerprint/apps/serve/services/furniture.py
taste-fingerprint/apps/serve/services/query_enhancer.py
taste-fingerprint/apps/web/.eslintrc.json
taste-fingerprint/apps/web/.prettierrc
taste-fingerprint/apps/web/app/globals.css
taste-fingerprint/apps/web/app/layout.tsx
taste-fingerprint/apps/web/app/onboarding/page.tsx
taste-fingerprint/apps/web/app/onboarding/styles.module.css
taste-fingerprint/apps/web/app/page.tsx
taste-fingerprint/apps/web/app/styles.module.css
taste-fingerprint/apps/web/lib/api.ts
taste-fingerprint/apps/web/next-env.d.ts
taste-fingerprint/apps/web/next.config.js
taste-fingerprint/apps/web/package.json
taste-fingerprint/apps/web/tsconfig.json
taste-fingerprint/docs/plan.md
taste-fingerprint/docs/prompt-experiments.md
taste-fingerprint/package.json
taste-fingerprint/packages/catalog/artworks.json
taste-fingerprint/packages/catalog/furniture_comprehensive.json
taste-fingerprint/packages/catalog/furniture_expanded_part1.json
taste-fingerprint/packages/catalog/furniture_old_22items.json
taste-fingerprint/packages/catalog/furniture.json
taste-fingerprint/packages/catalog/generate_catalog.py
taste-fingerprint/packages/catalog/products_clean.json
taste-fingerprint/packages/catalog/products_unique.json
taste-fingerprint/packages/catalog/products.json
taste-fingerprint/packages/catalog/SOURCES.md
taste-fingerprint/packages/catalog/UPGRADE_SUMMARY.md
test_3d_generation.html
test_claude_3d.py
TESTING.md
[1 more files omitted for size]
```

### Dependencies

- artspace-interior/artspace-ui/package.json: @react-three/drei@10.7.6, @react-three/fiber@9.4.0, @tailwindcss/postcss@^4, @types/node@^20, @types/react@^19, @types/react-dom@^19, @types/three@^0.180.0, eslint@^9, eslint-config-next@16.0.0, framer-motion@^12.23.24, lucide-react@^0.548.0, next@16.0.0, react@19.2.0, react-dom@19.2.0, tailwindcss@^4, three@^0.180.0, typescript@5.9.3
- taste-fingerprint/apps/serve/requirements.txt: anthropic, certifi, chromadb, fastapi, numpy, openai@>=1.50.0, pillow, pydantic@>=2.3,<3, python-dotenv, torch@>=2.6.0, transformers, uvicorn[standard]
- taste-fingerprint/apps/web/package.json: @types/node@20.14.12, @types/react@18.3.4, @types/react-dom@18.3.0, @types/uuid@^11.0.0, eslint@8.57.0, eslint-config-next@14.2.4, next@14.2.4, react@18.3.1, react-dom@18.3.1, typescript@5.5.4, uuid@^13.0.0

### Recent commits (newest first)

- Merge pull request #7 from MurtazaKafka/fronted
- update readme
- solving apps issue
- merge conflicts between main frontend and products
- Merge branch 'frontend' into demo
- Add new code for serving and rendering rooms
- resolving prod error
- quick change
- minor changes
- production values
- only allowing the option to generate from 2d image to 3d reconstruction
- fixed import issues as well as leaked api keys
- Add import statements and configuration for images in web app
- added claude 3d rendering and display functionality
- Add new code for product recommendations and clean product data
- feat: integrate claude room generator and embeddings
- Merge pull request #6 from MurtazaKafka/museum-ui
- Studio UI Page
- Merge pull request #5 from MurtazaKafka/summary
- Add new code for taste vector summarization and Claude integration

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

### DEPLOYMENT.md

```markdown
# Deployment Guide for artki.tech

This document captures a reproducible path for publishing the Interior Design platform to production at **https://artki.tech**.

---

## 1. Prerequisites

1. **Source Control**
   - Ensure the latest code is pushed to the `frontend` branch (or a dedicated `main`/`production` branch).
   - Render and Vercel can both deploy directly from GitHub.

2. **Environment Secrets**
   Collect the following values before creating services:

   | Variable | Description |
   | --- | --- |
   | `CHROMA_API_KEY` | ChromaDB Cloud API key |
   | `CHROMA_TENANT` | ChromaDB tenant/organization ID |
   | `CHROMA_DATABASE` | Database name (defaults to `taste-fingerprint`) |
   | `ANTHROPIC_API_KEY` | Claude 4.5 Sonnet API key |
   | `SKETCHFAB_TOKEN` | Token for retrieving Sketchfab assets (optional right now) |
   | `CORS_ALLOW_ORIGINS` | Comma-separated list of allowed origins (production + staging URLs) |
   | `NEXT_PUBLIC_TASTE_API_URL` | Public URL of the FastAPI backend |
   | `NEXT_PUBLIC_FURNITURE_API_URL` | Same as above unless split |
   | `NEXT_PUBLIC_NERF_API_URL` | (Optional) URL of NeRF/mesh service when online |

3. **One-time Data Seeding**
   - The furniture catalog must be embedded into Chroma once per environment.
   - Run `python scripts/embed_furniture.py` from `taste-fingerprint/apps/serve` with the production environment configured (can be run locally and pointed at production Chroma).

---

## 2. Backend (FastAPI) on Render

Render blueprint: [`render.yaml`](./render.yaml)

### 2.1 Create the service

1. Log into [Render](https://dashboard.render.com) and add a **Blueprint** from your GitHub repo.
2. Select the `render.yaml` file in the root when prompted.
3. Confirm the service `taste-fingerprint-api` is detected with **Environment = Python** and **Root Directory = `taste-fingerprint`** (Render will otherwise default to Node and try to run `yarn start`).
4. Verify the following commands are populated before deploying (Render currently ignores the optional `pythonVersion` key in blueprints—set the Python version in the dashboard after the service is created if you need something other than the default):
   - Python runtime 3.12
   - Build command: `pip install --upgrade pip && pip install -r apps/serve/requirements.txt`
   - Start command: `PYTHONPATH=. uvicorn apps.serve.main:app --host 0.0.0.0 --port 8000`

If a service was already created without the blueprint and Render is attempting `yarn start`, either delete the service and recreate it using the steps above, or edit the **Settings → Build & Deploy** tab to switch the environment to Python, set the root directory to `taste-fingerprint`, and enter the build/start commands manually.

### 2.2 Configure environment variables

Add values for each secret listed above. For convenience, `CORS_ALLOW_ORIGINS` already defaults to the production domain in `render.yaml`; add staging URLs as needed (comma-separated).

### 2.3 Post-deploy checklist

- After the first d
[truncated — 3233 more characters]
```

### DEMO_RUNBOOK.md

```markdown
# Artki.tech Demo Runbook

Live walkthrough plan for showcasing the end-to-end experience described in the Devpost submission.

## 0. Prerequisites (T-10 minutes)

1. **Backend environment**
   - `cd taste-fingerprint/apps/serve`
   - `python3 -m venv .venv && source .venv/bin/activate`
   - `pip install -r requirements.txt`
   - Provide `.env` with:
     ```bash
     CHROMA_API_KEY=...
     CHROMA_TENANT=...
     CHROMA_DATABASE=taste-fingerprint
     ANTHROPIC_API_KEY=...
     OPENAI_API_KEY=...
     CORS_ALLOW_ORIGINS=http://localhost:3000
     ```
   - Prime vector stores (only once per environment):
     ```bash
     python scripts/embed_furniture.py
     ```

2. **Frontend environment**
   - `cd artspace-interior/artspace-ui`
   - `npm install`
   - `.env.local` (adjust ports if needed)
     ```bash
     NEXT_PUBLIC_API_BASE=http://localhost:8000
     NEXT_PUBLIC_FURNITURE_API_URL=http://localhost:8000
     NEXT_PUBLIC_RENDER_ROOM_URL=http://localhost:8000
     ```

3. **Launch services (T-5)**
   - Backend: `uvicorn taste-fingerprint.apps.serve.main:app --reload --port 8000`
   - Frontend: `npm run dev`
   - Optional NeRF stub (not required for pivoted flow).

## Verification Snapshot (as of Oct 26)

| Command | Result | Notes |
| --- | --- | --- |
| `python3 -m compileall taste-fingerprint/apps/serve/main.py` | ✅ Pass | Confirms merged FastAPI module has no syntax errors. |
| `npm install` (artspace-ui) | ✅ Pass | Dependencies resolve; 0 vulnerabilities reported. |
| `npm run --prefix artspace-interior/artspace-ui build` | ⚠️ Compiles then exits 130 | Build succeeds before signal; warning about multiple lockfiles can be ignored for demo. |
| `npm run --prefix artspace-interior/artspace-ui lint` | ⚠️ Known rule violations | React hook lint warnings in `HeroCanvas`, `ScrollArtwork`, `TasteFingerprint` (safe to acknowledge during demo). |
| `python3 -m pytest taste-fingerprint` | ⚠️ Blocked | Terminates early awaiting SSH key passphrase; run manually if agent unlocked. |

## 1. Demo Script (7–9 minutes)

### Act I – Floorplan ➜ Room Canvas (90s)
1. Navigate to `http://localhost:3000`.
2. Use the hero scroll interaction to transition into the studio.
3. Step 1 card: upload `artspace-interior/artspace-ui/assets/floorplan.png` (or any PNG floorplan).
4. Hit **Continue to Style Selection** – explain Claude will convert the plan into Three.js geometry downstream (handled by `CompleteRoomGenerator`).

### Act II – Taste Discovery (2 min)
1. Step 2 shows the **TasteFingerprint** quiz (`TasteFingerprint.tsx`).
2. Walk through 12 comparisons (Monet vs. Picasso, etc.) – each click hits:
   - `POST /taste/update`
   - `POST /taste/summarize`
   - ChromaDB stores the evolving 512-D vector.
3. Call out `taste-fingerprint/apps/serve/main.py` sections:
   - `_ensure_sequence`, `_collect_keywords`
   - `taste_summarize` (Claude summarization)
   - Metadata caching for subsequent recommendations.

### Act III – 3D Room Generation (3 min)
1. Step 3 reveals `C
[truncated — 3304 more characters]
```

### taste-fingerprint/package.json

```
{
  "name": "taste-fingerprint",
  "private": true,
  "scripts": {
    "embed:artworks": "python apps/serve/scripts/embed_artworks.py"
  }
}

```

### artspace-interior/artspace-ui/package.json

```
{
  "name": "artspace-ui",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint"
  },
  "dependencies": {
  "framer-motion": "^12.23.24",
    "lucide-react": "^0.548.0",
    "next": "16.0.0",
    "react": "19.2.0",
    "react-dom": "19.2.0",
    "three": "^0.180.0",
  "@react-three/fiber": "9.4.0",
  "@react-three/drei": "10.7.6"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "@types/three": "^0.180.0",
    "eslint": "^9",
    "eslint-config-next": "16.0.0",
    "tailwindcss": "^4",
    "typescript": "5.9.3"
  }
}

```

### taste-fingerprint/apps/serve/requirements.txt

```
fastapi
uvicorn[standard]
pydantic>=2.3,<3
chromadb
numpy
pillow
torch>=2.6.0
transformers
python-dotenv
certifi
anthropic
openai>=1.50.0

```

### taste-fingerprint/apps/web/package.json

```
{
  "name": "web",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "14.2.4",
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "uuid": "^13.0.0"
  },
  "devDependencies": {
    "@types/node": "20.14.12",
    "@types/react": "18.3.4",
    "@types/react-dom": "18.3.0",
    "@types/uuid": "^11.0.0",
    "eslint": "8.57.0",
    "eslint-config-next": "14.2.4",
    "typescript": "5.5.4"
  }
}

```

### artspace-interior/artspace-ui/app/layout.tsx

```typescript
import type { Metadata } from "next";
import { Inter, Playfair_Display } from "next/font/google";
import "./globals.css";

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

const playfair = Playfair_Display({
  subsets: ["latin"],
  display: "swap",
  variable: "--font-playfair",
});

export const metadata: Metadata = {
  title: "ArtSpace — Spatial Design Studio",
  description: "Architecture as interface. Compose interiors through AI-guided curation and walk through your vision in 3D.",
};

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

```

### artspace-interior/artspace-ui/app/page.tsx

```typescript
'use client'

import { motion, useScroll, useTransform } from 'framer-motion'
import { useState, useEffect } from 'react'
import type { ChangeEvent } from 'react'

import { ZoomScene } from './components/ZoomScene'
import { PageBanner } from './components/PageBanner'
import { SectionCard } from './components/SectionCard'
import { StepHeader } from './components/StepHeader'
import { FloorplanUploader } from './components/FloorplanUploader'
import { TasteFingerprint } from './components/TasteFingerprint'
import { PageTransition } from './components/PageTransition'
import { ImageTo3D } from './components/ImageTo3D'
import { CompleteRoomGenerator } from './components/CompleteRoomGenerator'
import { fetchArtworks, type Artwork } from '@/lib/taste-api'

export default function HomePage() {
  const { scrollYProgress } = useScroll()
  const [hasStarted, setHasStarted] = useState(false)

  // Hero section fades out
  const heroOpacity = useTransform(scrollYProgress, [0, 0.12], [1, 0])
  const heroY = useTransform(scrollYProgress, [0, 0.12], [0, -50])

  // Canvas scroll progress (for camera zoom) - maps 15% to 75% scroll to 0-1
  const canvasScrollProgress = useTransform(scrollYProgress, [0.15, 0.75], [0, 1])

  // Act overlays inside the frame - extended visibility with hold periods
  const act1Opacity = useTransform(scrollYProgress, [0.2, 0.28, 0.38, 0.45], [0, 1, 1, 0])
  const act1Y = useTransform(scrollYProgress, [0.2, 0.28], [20, 0])
  const act2Opacity = useTransform(scrollYProgress, [0.42, 0.5, 0.6, 0.67], [0, 1, 1, 0])
  const act2Y = useTransform(scrollYProgress, [0.42, 0.5], [20, 0])
  const act3Opacity = useTransform(scrollYProgress, [0.64, 0.72, 0.82, 0.88], [0, 1, 1, 0])
  const act3Y = useTransform(scrollYProgress, [0.64, 0.72], [20, 0])

  // Canvas and final section crossfade (seamless transition)
  const canvasOpacity = useTransform(scrollYProgress, [0.08, 0.15, 0.85, 0.92], [0, 1, 1, 0])
  const finalOpacity = useTransform(scrollYProgress, [0.88, 0.95], [0, 1])
  const finalY = useTransform(scrollYProgress, [0.88, 0.95], [20, 0])

  // Convert scroll progress to 0-1 for ZoomScene
  const [zoomProgress, setZoomProgress] = useState(0)
  useEffect(() => {
    if (hasStarted) return
    const unsubscribe = canvasScrollProgress.on('change', (value) => {
      setZoomProgress(Math.max(0, Math.min(1, value)))
    })
    return () => unsubscribe()
  }, [canvasScrollProgress, hasStarted])

  const handleBeginScroll = () => {
    setHasStarted(true)
    const target = document.getElementById('studio')
    requestAnimationFrame(() => {
      target?.scrollIntoView({ behavior: 'smooth', block: 'start' })
    })
  }

  useEffect(() => {
    if (typeof window === 'undefined') return
    if (window.location.hash === '#studio') {
      setHasStarted(true)
    }
  }, [])

  useEffect(() => {
    if (hasStarted) return
    const unsubscribe = scrollYProgress.on('change', (value) => {
      if (value > 0.94) {
        setHasStarted(true)
      }
    })
    return () => unsubscribe()
  }, [scrollYProgress, hasStarted])

  const [currentStep, setCurrentStep] = useState(0)
  const [floorplan, setFloorplan] = useState<File | null>(null)
  const [floorplanPreview, setFloorplanPreview] = useState('')
  const [artworks, setArtworks] = useState<Artwork[]>([])
  const [isGeneratingFromImage, setIsGeneratingFromImage] = useState(false)
  const [showImageTo3D, setShowImageTo3D] = useState(false)
  const [userId] = useState<string>(
    () => `user_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`
  )

  useEffect(() => {
    fetchArtworks()
      .then(setArtworks)
      .catch((error) => {
        console.error('Failed to load artworks:', error)
      })
  }, [])

  const handleFloorplanUpload = (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (!file) return

    setFloorplan(file)
    const reader = new FileReader()
    reader.onloadend = () => {
      setFloorplanPreview(reader.result as string)
    }
    reader.readAsDataURL(file)
  }

  const handleFloorplanDrop = (files: FileList) => {
    const file = files[0]
    if (!file) return

    setFloorplan(file)
    const reader = new FileReader()
    reader.onloadend = () => {
      setFloorplanPreview(reader.result as string)
    }
    reader.readAsDataURL(file)
  }

  const handleFloorplanComplete = () => {
    setCurrentStep(1)
  }

  const handleTasteComplete = async (vector: number[]) => {
    console.info('Taste vector captured', vector.length)
    setCurrentStep(2)
  }

  const handleImageTo3D = async (imageUrl: string, description: string) => {
    setIsGeneratingFromImage(true)
    try {
      const response = await fetch('http://localhost:8000/api/image-to-3d', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          image_url: imageUrl,
          description,
          enhance_with_ai: true,
        }),
      })

      if (response.ok) {
        await response.json()
        setShowImageTo3D(false)
      }
    } catch (error) {
      console.error('Error generating 3D from image:', error)
    } finally {
      setIsGeneratingFromImage(false)
    }
  }

  return (
    <main className="relative bg-[var(--background)] text-[var(--foreground)]">
      {!hasStarted && (
        <>
          <section className="relative flex min-h-screen items-center justify-center">
            <motion.div 
              className="relative z-10 mx-auto flex max-w-[800px] flex-col items-center gap-10 px-8 text-center"
              style={{ opacity: heroOpacity, y: heroY }}
            >
              <motion.p 
                className="text-xs uppercase tracking-[0.35em] text-[var(--accent)]"
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ delay: 0.6, duration: 1.2 }}
              >
                Architecture as Interface
              </motion.p>
   
[truncated — 13418 more characters]
```

### taste-fingerprint/apps/web/app/layout.tsx

```typescript
import './globals.css';
import type { Metadata } from 'next';
import { ReactNode } from 'react';

export const metadata: Metadata = {
  title: 'Taste Fingerprint Onboarding',
  description: 'Discover your design taste through museum artworks',
};

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

```

### taste-fingerprint/apps/web/app/page.tsx

```typescript
import Link from 'next/link';
import styles from './styles.module.css';

export default function HomePage() {
  return (
    <main className={styles.hero}>
      <div className={styles.heroCard}>
        <h1>Taste Fingerprint</h1>
        <p>
          Explore museum masterpieces to map your interior design taste. Complete a quick
          set of A/B choices and we will craft your unique fingerprint.
        </p>
        <Link href="/onboarding" className={styles.cta}>
          Start Onboarding
        </Link>
      </div>
    </main>
  );
}

```

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