By Nehan Mohammed, Rian Sen Majumder, and Simon Akhter
Vite + React + TypeScript single-page app that matches the requested McMaster-themed lost & found marketplace:
- Landing hero with McMaster maroon/gold palette
- Marketplace
/lostwith search + filters, blurred thumbnails, AI metadata chips - Found dashboard
/foundto post items (photo upload + location hint) and see your postings - Item detail
/items/:idwith claim flow and chat entry - Chat
/chat/:itemId/:otherUserIdwith safe-meetup banner
If Supabase environment vars are missing, the app runs in demo mode with seeded data so the UX still works offline. Supabase integration is wired and will activate once env vars are provided.
npm install
npm run devThen open the printed local URL.
Create a .env (or .env.local) with:
VITE_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
VITE_SUPABASE_ANON_KEY=YOUR_ANON_KEY
Buckets/tables expected:
- Bucket
item-images - Tables:
items,item_images,ai_image_analyses,messages - Suggested schema tweaks:
alter table items add column if not exists category text;andalter table item_images add column if not exists is_blurred boolean default true;
Supabase Auth (Email magic link) with enforcement:
- Login prompts for a
@mcmaster.caemail, then sends a magic link viasupabase.auth.signInWithOtp({ email, options: { emailRedirectTo } }) - After session, users without
@mcmaster.caare signed out with an error message. - Demo mode signs in a stub user when Supabase is not configured.
Use this JSON contract after uploading the image to storage:
Return JSON with keys:
category: one of ["electronics","clothing","id","keys","bag","book","water_bottle","sports","other"]
vague_label: short 2-5 word human-friendly label
tags: array of keywords (brand/model/object/material)
colors: array of main colors
materials: array of materials (optional)
confidence: number 0-1 for the category choice
If multiple items, pick the dominant lost item. Do not include any extra text.
Use the JSON to insert ai_image_analyses and update items.vague_description, items.metadata, items.category, and items.best_ai_confidence.
/— Landing hero + CTAs (login, “I lost”, “I found”), blur messaging, AI note./lost— Search + filters (category, location, time), marketplace grid with blurred cards./found— Upload photo, location hint, optional description/quiz hint; shows “My posted items.”/items/:id— Blurred image, metadata, AI confidence, claim form, owner chat links./chat/:itemId/:otherUserId— Message thread view with safe meetup suggestions.
- Images are blurred via CSS (
filter: blur(12px)) per MVP requirement. - Demo content lives in
src/data/demo.tsso the app feels alive without a backend.
Location: backend/
What it does:
- POST
/api/upload-itemwith multipart fieldimage→ Gemini vision extracts{object_type, color}→ inserts intoitemstable.
Setup:
- Copy
backend/.env.exampletobackend/.envand fill:SUPABASE_URLSUPABASE_SERVICE_KEY(service role; keep server-only)GEMINI_API_KEYPORT(optional, defaults to 3001)
- Install deps and run:
cd backend npm install npm run start # or npm run dev for watch
- Ensure Supabase table
itemshas columnsobject_typeandcolor(or adjust insert logic inbackend/server.js).
Endpoint usage example (curl):
curl -F "image=@/path/to/photo.jpg" http://localhost:3001/api/upload-item