# Project export: Nexus

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: The AI-powered search engine and packing optimizer for your physical gear.
- Devpost: https://devpost.com/software/nexus-dnjzhq
- GitHub: https://github.com/Bmohmand/Nexus
- Video: https://www.youtube.com/embed/rGDcrKwt-lk?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 5 GitHub contributor(s) — Bahram Mohmand (60 commits), NoahSabb (53 commits), Zihan Wang (51 commits), Claude (8 commits), Cursor (2 commits)

## Devpost submission (written by the team)

### Inspiration

If you forget a toothbrush on a vacation, it’s annoying. If you pack the wrong gear for a disaster relief mission, it’s dangerous. Right now, logistics coordinators for high-stakes deployments—whether it’s search-and-rescue or remote medical aid—are still relying on spreadsheets and mental math. They have to mentally juggle weight limits, material science (e.g., knowing that "cotton kills" in hypothermia scenarios), and cross-domain utility (a mylar blanket is both shelter and medical gear). We asked a simple question: Why can we search the entire internet in milliseconds, but we still have to rummage through bins to find our own stuff? We built Nexus to digitize the physical world and treat packing like the mathematical optimization problem it actually is.

### What it does

Nexus is a search engine and logistics officer for your physical gear. It "Sees" Physics: You don't type in data. You just snap a photo. Nexus analyzes the image to understand not just what an item is, but what it does. It extracting factors such as thermal ratings, materials, waterproofing, and medical utility automatically. It Understands Context: You don't search for "flashlights." You search for "lighting for a power outage in heavy rain." Nexus understands the semantic difference between a keychain light and a tactical floodlight. It Reasons for Safety: A cross-domain synthesis layer actively rejects dangerous item selections (e.g., packing cotton clothing for cold-weather survival) and explains why, flagging critical gaps like "No water purification detected." It Solves the Knapsack Problem: You give it a mission ("72-hour cold-climate medical response") and constraints ("Bag with 15kg Weight Limit"). Nexus uses a constraint solver to mathematically prove the optimal loadout, ensuring you have enough medical gear without blowing your weight limit on heavy batteries.

### How we built it

The "Eyes" (Vision & Extraction): We pipe camera feeds from Flutter directly to GPT-5. We prompt-engineered it to act like a materials scientist, extracting structured JSON metadata about an item's capabilities and failure modes via strict schema validation. The "Eyes" (Vision & Extraction): We pipe camera feeds from Flutter directly to GPT-5. We prompt-engineered it to act like a materials scientist, extracting structured JSON metadata about an item's capabilities and failure modes via strict schema validation. The "Brain" (Multimodal Embeddings): Standard text embeddings weren't enough. We used Voyage AI’s voyage-multimodal-3.5 model to generate 1024-dimensional vectors from the interleaved image plus serialized context text. This eliminates the modality gap, ensuring the vector representation includes both visual textures and explicitly extracted metadata. The "Brain" (Multimodal Embeddings): Standard text embeddings weren't enough. We used Voyage AI’s voyage-multimodal-3.5 model to generate 1024-dimensional vectors from the interleaved image plus serialized context text. This eliminates the modality gap, ensuring the vector representation includes both visual textures and explicitly extracted metadata. The "Memory" (Vector DB): We utilized Supabase with the pgvector extension and HNSW indexing. It handles both relational metadata and lightning-fast cosine similarity search in a single instance. The "Memory" (Vector DB): We utilized Supabase with the pgvector extension and HNSW indexing. It handles both relational metadata and lightning-fast cosine similarity search in a single instance. The "Math" (Optimization): We use the Google OR-Tools CP-SAT solver to run a bounded knapsack optimization. It balances diversity (e.g., minimum medical items, tag requirements) against weight limits across multi-container bin packing scenarios. The "Math" (Optimization): We use the Google OR-Tools CP-SAT solver to run a bounded knapsack optimization. It balances diversity (e.g., minimum medical items, tag requirements) against weight limits across multi-container bin packing scenarios.

### Challenges we ran into

Dangerous Recommendations: Naive vector search returned items that were semantically similar but contextually dangerous (e.g., cotton for cold weather). We fixed this by explicitly extracting unsuitable_contexts and failure_modes during vision analysis, embedding them as first-class features. Dangerous Recommendations: Naive vector search returned items that were semantically similar but contextually dangerous (e.g., cotton for cold weather). We fixed this by explicitly extracting unsuitable_contexts and failure_modes during vision analysis, embedding them as first-class features. A user might ask for "3 medical items" when they only own 2. A standard solver just crashes and says "Infeasible." We had to write a wrapper that progressively relaxes constraints (e.g., dropping the item count requirement) so the app can say, "I couldn't find 3 items, but here are the 2 you have," instead of just throwing an error. A user might ask for "3 medical items" when they only own 2. A standard solver just crashes and says "Infeasible." We had to write a wrapper that progressively relaxes constraints (e.g., dropping the item count requirement) so the app can say, "I couldn't find 3 items, but here are the 2 you have," instead of just throwing an error. Weight Estimation without Scales: Most users don't know the exact weight of their gear. We built an AI weight estimation system that maps vision-inferred categories to gram estimates, allowing the knapsack solver to function without precise data. Weight Estimation without Scales: Most users don't know the exact weight of their gear. We built an AI weight estimation system that maps vision-inferred categories to gram estimates, allowing the knapsack solver to function without precise data. Accomplishments It actually works in 5 seconds: We managed to get the full pipeline—snap photo → GPT-5 Vision extraction → Multimodal Embedding → Database Write. Watching a raw image turn into a queryable, data-rich inventory item feels like magic every time. It actually works in 5 seconds: We managed to get the full pipeline—snap photo → GPT-5 Vision extraction → Multimodal Embedding → Database Write. Watching a raw image turn into a queryable, data-rich inventory item feels like magic every time. Cross-Domain Reasoning: We didn't hardcode rules. The system learned that a sleeping bag is useful for medical shock treatment purely through semantic similarity. Cross-Domain Reasoning: We didn't hardcode rules. The system learned that a sleeping bag is useful for medical shock treatment purely through semantic similarity. Optimal Packing: We aren't just guessing. When Nexus tells you what to pack, it's mathematically the best possible combination of items for your specific weight limit. Optimal Packing: We aren't just guessing. When Nexus tells you what to pack, it's mathematically the best possible combination of items for your specific weight limit. Visualizing the "Latent Space": We didn't just store vectors; we visualized them. We built a 3D force-directed graph (using a WebView bridge to React Three Fiber) that lets users physically "fly" through their inventory. You can visually see how "Batteries" cluster near "Flashlights" but far from "Socks," turning abstract math into a tangible map. Visualizing the "Latent Space": We didn't just store vectors; we visualized them. We built a 3D force-directed graph (using a WebView bridge to React Three Fiber) that lets users physically "fly" through their inventory. You can visually see how "Batteries" cluster near "Flashlights" but far from "Socks," turning abstract math into a tangible map.

### What we learned

Optimization > Search: Semantic search is cool, but it's easy. The real value is in the constraint solver. People don't just want to find their gear; they want mathematical proof of what they should take. Vision Models are Materials Scientists: We were surprised by how much physical intuition GPT-5 Vision has. It correctly identified that a specific fabric looked like ripstop nylon without us telling it.

### What's next

Team Mode & Collaborative Inventories: Shared loadouts for search-and-rescue teams or expedition groups with role-based access (e.g., "I have the tent, you bring the stove"). Hardware Integration: Connecting to Bluetooth luggage scales to track weight in real-time as you drop items into the box. Historical Analytics: Letting users rate their loadout post-mission ("The heavy sleeping bag was overkill") so the model learns preferences and improves future packing recommendations.

## README (from the GitHub repository)

# Nexus

**AI-powered packing intelligence for missions, travel, and logistics.**

Nexus turns your physical inventory into a searchable, semantically-rich vector database. Photograph your items, describe your mission in plain English, and get an optimized, LLM-explained packing manifest in seconds.

---

## Architecture

```mermaid
flowchart LR
    subgraph frontend [Flutter Frontend]
        Camera[Camera Scan]
        Search[NL Search]
        Grid[Items Grid]
    end

    subgraph backend [FastAPI Backend]
        Ingest[Ingest Route]
        SearchRoute[Search Route]
        PackRoute[Pack Route]
    end

    subgraph ai [AI Pipeline]
        Vision["GPT-5 Vision\n(Context Extraction)"]
        Voyage["Voyage AI\n(Multimodal Embedding)"]
        Synth["GPT-5 LLM\n(Mission Synthesis)"]
        Knapsack["OR-Tools CP-SAT\n(Knapsack Optimizer)"]
    end

    subgraph db [Supabase]
        PG["PostgreSQL + pgvector"]
        Storage["Storage Bucket\n(manifest-assets)"]
    end

    Camera --> Ingest
    Ingest --> Vision --> Voyage --> PG
    Ingest --> Storage
    Search --> SearchRoute --> Voyage
    Voyage --> PG
    PG --> Synth --> Grid
    PG --> Knapsack --> PackRoute
```

### Data Flows

**Ingest** — Image → GPT-5 Vision extracts structured context (material, thermal rating, medical use, durability, tags) → Voyage AI generates 1024-dim multimodal embedding → Supabase upsert + Storage upload

**Search** — Natural language query → Voyage AI embeds query → pgvector cosine similarity search → GPT-5 LLM curates results into an explained mission plan

**Pack** — Search results → OR-Tools CP-SAT bounded knapsack solver (weight limits, category diversity, tag requirements) → Optimized manifest with constraint relaxation reporting

---

## Tech Stack

| Layer | Technology |
|---|---|
| **Languages** | Python 3.13, Dart, SQL |
| **Frontend** | Flutter (Material 3), Dio, Supabase Flutter SDK, Image Picker |
| **Backend** | FastAPI, Uvicorn, Pydantic, HTTPX |
| **AI — Vision** | OpenAI GPT-5 Vision (structured context extraction) |
| **AI — Embeddings** | Voyage AI `voyage-multimodal-3.5` (1024-dim), CLIP ViT-B-32 (offline fallback) |
| **AI — Synthesis** | OpenAI GPT-5 (mission plan curation) |
| **Optimization** | Google OR-Tools CP-SAT Solver (bounded knapsack) |
| **Database** | Supabase PostgreSQL + pgvector |
| **Storage** | Supabase Storage (`manifest-assets` bucket) |
| **Utilities** | NumPy, Pillow, python-dotenv |

---

## Project Structure

```
nexus/
├── backend/
│   ├── ai_modules/              # Core AI pipeline
│   │   ├── config.py            # API keys, model config, constants
│   │   ├── context_extractor.py # GPT-5 Vision → structured ItemContext
│   │   ├── embedding_engine.py  # Voyage multimodal + CLIP fallback
│   │   ├── knapsack_optimizer.py# OR-Tools CP-SAT bounded knapsack
│   │   ├── mission_synthesizer.py# GPT-5 mission plan generation
│   │   ├── models.py            # Pydantic data models
│   │   ├── pipeline.py          # Top-level orchestrator (ingest/search/pack)
│   │   ├── vector_store.py      # Supabase pgvector integration
│   │   └── test_images/         # Sample images (camping, clothing, medical, tech)
│   ├── server/                  # FastAPI HTTP layer
│   │   ├── main.py              # App entry point, CORS, lifespan
│   │   ├── dependencies.py      # Singleton pipeline injection
│   │   ├── schemas.py           # Request/response Pydantic models
│   │   └── routes/
│   │       ├── ingest.py        # POST /api/v1/ingest, /ingest/upload
│   │       ├── search.py        # POST /api/v1/search/semantic
│   │       ├── pack.py          # POST /api/v1/pack
│   │       ├── items.py         # GET  /api/v1/items
│   │       └── containers.py    # CRUD /api/v1/containers
│   ├── migrations/              # SQL migrations (001–013)
│   ├── requirements.txt         # All Python dependencies
│   ├── seed_test_images.py      # Batch ingest local test images
│   ├── seed_dummyjson.py        # Batch ingest from DummyJSON API
│   └── .env                     # Environment variables (not committed)
├── frontend/
│   ├── lib/
│   │   ├── main.dart            # Flutter app (4-tab UI)
│   │   └── api_service.dart     # Backend API client
│   ├── pubspec.yaml             # Dart dependencies
│   └── .env                     # Frontend environment variables
└── README.md                    # This file
```

---

## Setup

### Prerequisites

- Python 3.13+
- Flutter SDK 3.2+
- A [Supabase](https://supabase.com) project with pgvector enabled
- API keys: [OpenAI](https://platform.openai.com), [Voyage AI](https://voyageai.com)

### 1. Database Setup

1. Open your Supabase project dashboard.
2. Go to **SQL Editor** and run the migrations in order:
   ```
   backend/migrations/001_extensions.sql
   backend/migrations/002_enums.sql
   backend/migrations/003_profiles.sql
   backend/migrations/004_manifest_items.sql
   backend/migrations/005_missions.sql
   backend/migrations/006_mission_items.sql
   backend/migrations/007_rls_policies.sql
   backend/migrations/008_vector_search.sql
   backend/migrations/009_storage_policies.sql
   backend/migrations/010_allow_null_user_id.sql
   backend/migrations/011_storage_containers.sql
   backend/migrations/012_enhanced_context_fields.sql
   backend/migrations/013_enhanced_vector_search.sql
   ```
   Or run `000_run_all_manifest.sql` which includes all of the above.
3. Go to **Storage** → **New bucket** → Name: `manifest-assets` → Public: **ON**.

### 2. Backend Setup

```bash
cd backend

# Create virtual environment
python -m venv .venv
# Windows:
.\.venv\Scripts\Activate.ps1
# macOS/Linux:
source .venv/bin/activate

# Install all dependencies
pip install -r requirements.txt

# Configure environment
cp .env.example .env   # Then edit with your API keys
```

**`backend/.env`** requires:

| Variable | Description |
|---|---|
| `OPENAI_API_KEY` | OpenAI API key (for GPT-5 Vision + synthesis) |
| `VOYAGE_API_KEY` | Voyage AI API key (for multimodal embeddings) |
| `SUPABASE_URL` | Supabase project URL |
| `SUPABASE_SERVICE_KEY` | Supabase **service_role** key (not the anon key) |
| `API_BASE_URL` | Backend URL, default `http://localhost:8000` |

**Run the server:**

```bash
python -m uvicorn server.main:app --reload --port 8000
```

API docs available at `http://localhost:8000/docs`.

### 3. Frontend Setup

```bash
cd frontend

# Install Dart dependencies
flutter pub get
```

Create `frontend/.env`:
```
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key
API_BASE_URL=http://localhost:8000
```

**Run the app:**

```bash
flutter run
```

---

## Seed Data

Populate your Supabase database with sample items:

**Local test images** (34 items across camping, clothing, medical, tech):
```bash
cd backend
python seed_test_images.py
```

**DummyJSON products** (100 diverse items from a public API):
```bash
cd backend
python seed_dummyjson.py
```

Each seed script uploads images to Supabase Storage, runs GPT-5 Vision context extraction, generates Voyage multimodal embeddings, and upserts everything into the `manifest_items` table.

---

## API Endpoints

All routes are prefixed with `/api/v1`.

| Method | Endpoint | Description |
|---|---|---|
| `POST` | `/ingest` | Ingest item by image URL |
| `POST` | `/ingest/upload` | Ingest item by file upload |
| `POST` | `/search/semantic` | Natural language semantic search |
| `GET` | `/items` | List all items in the database |
| `POST` | `/pack` | Search + knapsack optimization |
| `GET/POST` | `/containers` | CRUD for storage containers |
| `GET` | `/health` | Health check |

---

## AI Pipeline Detail

### 1. Context Extraction (`context_extractor.py`)
GPT-5 Vision analyzes each item photo and returns structured JSON: name, category, material, weight estimate, thermal rating, water resistance, medical application, utility summary, semantic tags, durability, and compressibility.

### 2. Multimodal Embedding (`embedding_engine.py`)
Voyage AI `voyage

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 104 recognized source files, 543 KB.
- C (language) — detected in the code
- C++ (language) — detected in the code
- Dart (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- Kotlin (language) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- PyTorch (technology) — detected in the code
- SQL (language) — detected in the code
- Supabase (technology) — detected in the code
- Swift (language) — detected in the code
- PostgreSQL (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers
- AI coding agent: Cursor — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (120 of 172)

```
.DS_Store
.gitignore
.idea/.gitignore
.idea/caches/deviceStreaming.xml
.idea/libraries/Dart_Packages.xml
.idea/libraries/Dart_SDK.xml
.idea/misc.xml
.idea/modules.xml
.idea/vcs.xml
.mailmap
backend/ai_modules/__init__.py
backend/ai_modules/config.py
backend/ai_modules/context_extractor.py
backend/ai_modules/embedding_engine.py
backend/ai_modules/embedding_tests/__init__.py
backend/ai_modules/embedding_tests/_import_helper.py
backend/ai_modules/embedding_tests/conftest.py
backend/ai_modules/embedding_tests/test_embedding_engine.py
backend/ai_modules/embedding_tests/test_embeddings.py
backend/ai_modules/embedding_tests/test_knapsack_with_embeddings.py
backend/ai_modules/embedding_tests/test_live_integration.py
backend/ai_modules/embedding_tests/test_live_supabase.py
backend/ai_modules/embedding_tests/test_models.py
backend/ai_modules/embedding_tests/test_pipeline.py
backend/ai_modules/embedding_tests/test_vector_store.py
backend/ai_modules/knapsack_optimizer.py
backend/ai_modules/mission_synthesizer.py
backend/ai_modules/models.py
backend/ai_modules/pipeline.py
backend/ai_modules/requirements.txt
backend/ai_modules/vector_store.py
backend/conftest.py
backend/migrations/000_run_all_manifest.sql
backend/migrations/001_extensions.sql
backend/migrations/002_enums.sql
backend/migrations/003_profiles.sql
backend/migrations/004_manifest_items.sql
backend/migrations/005_missions.sql
backend/migrations/006_mission_items.sql
backend/migrations/007_rls_policies.sql
backend/migrations/008_vector_search.sql
backend/migrations/009_storage_policies.sql
backend/migrations/010_allow_null_user_id.sql
backend/migrations/011_storage_containers.sql
backend/migrations/012_enhanced_context_fields.sql
backend/migrations/013_enhanced_vector_search.sql
backend/migrations/README_STORAGE.md
backend/package.json
backend/pytest.ini
backend/README.md
backend/requirements.txt
backend/run_server.bat
backend/scripts/reembed_all_items.py
backend/server/__init__.py
backend/server/dependencies.py
backend/server/main.py
backend/server/requirements.txt
backend/server/routes/__init__.py
backend/server/routes/containers.py
backend/server/routes/ingest.py
backend/server/routes/items.py
backend/server/routes/pack.py
backend/server/routes/search.py
backend/server/schemas.py
FitCheck.iml
frontend/.gitignore
frontend/.metadata
frontend/analysis_options.yaml
frontend/android/.gitignore
frontend/android/app/build.gradle.kts
frontend/android/app/src/debug/AndroidManifest.xml
frontend/android/app/src/main/AndroidManifest.xml
frontend/android/app/src/main/kotlin/com/example/nexus/MainActivity.kt
frontend/android/app/src/main/res/drawable-v21/launch_background.xml
frontend/android/app/src/main/res/drawable/launch_background.xml
frontend/android/app/src/main/res/values-night/styles.xml
frontend/android/app/src/main/res/values/styles.xml
frontend/android/app/src/profile/AndroidManifest.xml
frontend/android/build.gradle.kts
frontend/android/gradle.properties
frontend/android/gradle/wrapper/gradle-wrapper.properties
frontend/android/settings.gradle.kts
frontend/ios/.gitignore
frontend/ios/Flutter/AppFrameworkInfo.plist
frontend/ios/Flutter/Debug.xcconfig
frontend/ios/Flutter/Release.xcconfig
frontend/ios/Podfile
frontend/ios/Podfile.lock
frontend/ios/Runner.xcodeproj/project.pbxproj
frontend/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
frontend/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
frontend/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
frontend/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
frontend/ios/Runner.xcworkspace/contents.xcworkspacedata
frontend/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
frontend/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
frontend/ios/Runner/AppDelegate.swift
frontend/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
frontend/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
frontend/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
frontend/ios/Runner/Base.lproj/LaunchScreen.storyboard
frontend/ios/Runner/Base.lproj/Main.storyboard
frontend/ios/Runner/Info.plist
frontend/ios/Runner/Runner-Bridging-Header.h
frontend/ios/Runner/SceneDelegate.swift
frontend/ios/RunnerTests/RunnerTests.swift
frontend/lib/api_service.dart
frontend/lib/core/constants.dart
frontend/lib/core/platform_utils_io.dart
frontend/lib/core/platform_utils_stub.dart
frontend/lib/core/platform_utils.dart
frontend/lib/main.dart
frontend/lib/models/search_result.dart
frontend/lib/models/storage_container.dart
frontend/lib/models/vault_item.dart
frontend/linux/.gitignore
frontend/linux/CMakeLists.txt
frontend/linux/flutter/CMakeLists.txt
frontend/linux/flutter/generated_plugin_registrant.cc
frontend/linux/flutter/generated_plugin_registrant.h
[52 more files omitted for size]
```

### Dependencies

- backend/ai_modules/requirements.txt: httpx@>=0.26.0, numpy@>=1.24.0, open-clip-torch@>=2.24.0, openai@>=1.12.0, ortools@>=9.8, Pillow@>=10.0.0, pydantic@>=2.5.0, supabase@>=2.3.0, torch@>=2.1.0, torchvision@>=0.16.0, voyageai@>=0.3.0
- backend/package.json: uvicorn@^0.0.1-security
- backend/requirements.txt: fastapi@>=0.109.0, httpx@>=0.26.0, numpy@>=1.24.0, open-clip-torch@>=2.24.0, openai@>=1.12.0, ortools@>=9.8, Pillow@>=10.0.0, pydantic@>=2.5.0, python-dotenv@>=1.0.0, python-multipart@>=0.0.6, requests@>=2.31.0, supabase@>=2.3.0, torch@>=2.1.0, torchvision@>=0.16.0, uvicorn[standard]@>=0.27.0, voyageai@>=0.3.0
- backend/server/requirements.txt: fastapi@>=0.109.0, python-dotenv@>=1.0.0, python-multipart@>=0.0.6, uvicorn[standard]@>=0.27.0

### Recent commits (newest first)

- filter
- refresh working for graph
- changed nexus
- Merge branch 'main' of https://github.com/Bmohmand/FitCheck
- updater
- Merge pull request #10 from Bmohmand/claude/add-item-delete-button-gMdMO
- Add item delete button to ItemDetailPage
- revert some changes back to working graph view
- Remove old files
- Merge pull request #9 from Bmohmand/temp
- Merge branch 'temp' of https://github.com/Bmohmand/FitCheck into temp
- graph working!
- chore: add mailmap to clean up contributors list
- update readme and requirements
- update text in UI
- Merge branch 'temp' of https://github.com/Bmohmand/FitCheck into temp
- update supabase
- graph template
- graph template
- Merge branch 'temp' of https://github.com/Bmohmand/FitCheck into temp

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

### backend/migrations/README_STORAGE.md

```markdown
# Manifest — Storage bucket setup

The app uploads item images to Supabase Storage. You need to (1) create the bucket and (2) add Storage RLS policies so uploads are allowed. Otherwise you get **"new row violates row-level security policy"** (403).

## 1. Create the bucket

1. Open your project in **Supabase Dashboard**: https://supabase.com/dashboard
2. Go to **Storage** in the left sidebar.
3. Click **New bucket**.
4. **Name:** `manifest-assets` (must match exactly).
5. **Public bucket:** turn **ON** so the app and the AI backend can use the image URLs.
6. Click **Create bucket**.

## 2. Allow uploads (Storage RLS)

Supabase applies RLS to `storage.objects`. By default, no one can insert, so uploads return 403 until you add policies.

**Option A — SQL (recommended)**  
In **SQL Editor** → New query, paste and run the contents of **`009_storage_policies.sql`**. That adds policies so `manifest-assets` allows public insert/select/update/delete.

**Option B — Dashboard**  
Storage → **manifest-assets** → **Policies** → New policy. Add an **Insert** policy for "All users" (or "Authenticated users" if you only want logged-in uploads) with condition `bucket_id = 'manifest-assets'`. Add a **Select** policy the same way so reads work.

After both steps, "Analyze & Add to Vault" should work without the RLS error.

```

### backend/package.json

```
{
  "dependencies": {
    "uvicorn": "^0.0.1-security"
  }
}

```

### backend/requirements.txt

```
# Nexus — All Python Dependencies
# Install: pip install -r requirements.txt

# ── API Server ──────────────────────────────────────────────────────
fastapi>=0.109.0
uvicorn[standard]>=0.27.0
python-multipart>=0.0.6          # File uploads (multipart/form-data)
python-dotenv>=1.0.0             # Load .env files

# ── Data Validation ─────────────────────────────────────────────────
pydantic>=2.5.0

# ── AI / LLM ───────────────────────────────────────────────────────
openai>=1.12.0                   # GPT-5 Vision (context extraction) + GPT-5 (synthesis)
voyageai>=0.3.0                  # Voyage multimodal-3.5 embeddings

# ── Embeddings — Local CLIP Fallback (optional, for offline dev) ───
open-clip-torch>=2.24.0
torch>=2.1.0
torchvision>=0.16.0
Pillow>=10.0.0                   # Image preprocessing

# ── Vector Database ─────────────────────────────────────────────────
supabase>=2.3.0                  # Supabase client (PostgreSQL + pgvector via RPC)

# ── Optimization ────────────────────────────────────────────────────
ortools>=9.8                     # Google OR-Tools CP-SAT solver (knapsack)

# ── HTTP / Networking ───────────────────────────────────────────────
httpx>=0.26.0                    # Async HTTP client (URL image fetching)
requests>=2.31.0                 # Sync HTTP client (seed scripts, DummyJSON)

# ── Utilities ───────────────────────────────────────────────────────
numpy>=1.24.0                    # Vector operations

```

### backend/server/requirements.txt

```
# Manifest API Server
# NOTE: Prefer installing from the consolidated file:
#   pip install -r backend/requirements.txt
# This file is kept for reference.
fastapi>=0.109.0
uvicorn[standard]>=0.27.0
python-multipart>=0.0.6       # For file uploads
python-dotenv>=1.0.0         # Load .env from backend/

# Inherit ai_modules deps (install both requirement files)
# pip install -r ai_modules/requirements.txt -r server/requirements.txt

```

### backend/ai_modules/requirements.txt

```
# Nexus AI Pipeline - Requirements
# NOTE: Prefer installing from the consolidated file:
#   pip install -r backend/requirements.txt
# This file is kept for reference.

# Core
pydantic>=2.5.0
openai>=1.12.0           # GPT-5 Vision + synthesis

# Vector Database
supabase>=2.3.0           # Supabase client (includes pgvector via RPC)

# Knapsack Optimizer
ortools>=9.8               # Google OR-Tools CP-SAT solver

# Embedding Provider
voyageai>=0.3.0           # Voyage multimodal-3.5 (recommended)

# Local CLIP fallback (for dev/offline)
open-clip-torch>=2.24.0
torch>=2.1.0
torchvision>=0.16.0
Pillow>=10.0.0

# Async HTTP (for URL image fetching)
httpx>=0.26.0

# Utilities
numpy>=1.24.0

```

### backend/server/main.py

```python
"""
Manifest API — FastAPI Application
====================================
The HTTP middleware that connects the Flutter frontend to the AI pipeline.

Start with:
    uvicorn backend.server.main:app --reload --port 8000

Or from the backend/ directory:
    uvicorn server.main:app --reload --port 8000
"""

import logging
from pathlib import Path
from contextlib import asynccontextmanager

from dotenv import load_dotenv

# Load backend/.env before any component reads os.environ
_env_path = Path(__file__).resolve().parent.parent / ".env"
load_dotenv(_env_path)

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from .dependencies import get_pipeline
from .routes import ingest, search, pack, items, containers

# ---------------------------------------------------------------------------
# Logging
# ---------------------------------------------------------------------------
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(name)-20s | %(levelname)-7s | %(message)s",
    datefmt="%H:%M:%S",
)
logger = logging.getLogger("manifest.server")


# ---------------------------------------------------------------------------
# Lifespan: warm up the pipeline at startup
# ---------------------------------------------------------------------------
@asynccontextmanager
async def lifespan(app: FastAPI):
    """Initialize the AI pipeline once at server startup."""
    logger.info("Starting Manifest API server...")
    pipeline = get_pipeline()
    count = await pipeline.item_count()
    logger.info(f"Pipeline ready. {count} items in database.")
    yield
    logger.info("Manifest API server shutting down.")


# ---------------------------------------------------------------------------
# App
# ---------------------------------------------------------------------------
app = FastAPI(
    title="Manifest API",
    description="AI-powered search engine for physical assets",
    version="1.0.0",
    lifespan=lifespan,
)

# CORS — allow Flutter web & mobile to connect
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Tighten in production
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ---------------------------------------------------------------------------
# Routes
# ---------------------------------------------------------------------------
app.include_router(ingest.router, prefix="/api/v1", tags=["Ingest"])
app.include_router(search.router, prefix="/api/v1", tags=["Search"])
app.include_router(pack.router, prefix="/api/v1", tags=["Pack"])
app.include_router(items.router, prefix="/api/v1", tags=["Items"])
app.include_router(containers.router, prefix="/api/v1", tags=["Containers"])


@app.get("/health")
async def health():
    return {"status": "ok", "service": "manifest-api"}

```

### .idea/vcs.xml

```xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="VcsDirectoryMappings">
    <mapping directory="" vcs="Git" />
  </component>
</project>
```

### .idea/misc.xml

```xml
<project version="4">
  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
    <output url="file://$PROJECT_DIR$/out" />
  </component>
</project>
```

### .idea/modules.xml

```xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/FitCheck.iml" filepath="$PROJECT_DIR$/FitCheck.iml" />
    </modules>
  </component>
</project>
```

### frontend/pubspec.yaml

```yaml
name: nexus
description: Physical World API - Transform objects into searchable vector embeddings
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: '>=3.2.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
    
  http: ^1.1.0
  image_picker: ^1.0.4
  path_provider: ^2.1.1
  path: ^1.8.3
  vector_math: ^2.1.4
  # HTTP client for FastAPI backend
  dio: ^5.7.0
  # Environment variables
  flutter_dotenv: ^5.2.1
  # Supabase (Storage upload, optional auth)
  supabase_flutter: ^2.8.0
  # Image picker for camera/gallery
  webview_flutter: ^4.4.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.0

flutter:
  uses-material-design: true
  assets:
    - .env
  # Uncomment to add custom fonts
  # fonts:
  #   - family: Geist
  #     fonts:
  #       - asset: fonts/Geist-Regular.ttf
  #       - asset: fonts/Geist-Bold.ttf
  #         weight: 700
```

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