A minimal MVP that demonstrates AI-powered matching between lost and found item reports. This repository includes a Node/Express backend (AI matching using OpenAI/Hugging Face with a deterministic fallback), a React/Vite frontend, mock data, and debug helpers so you can test matching behavior locally.
- Implemented an AI embedding service (
aiService.js) that tries OpenAI embeddings first, then Hugging Face, and falls back to a deterministicdummyEmbeddingso the app works without API keys. - Created/refined mock data in
mockData.js: the app ships with 150 found items (first one is a seeded deterministic example) and no lost items (so lost submissions come from users during demo). - Built a small Express server (
server.js) exposing:POST /found-item— report a found itemPOST /lost-item— report a lost item and receive matches (finder emails) if anyGET /health— health checkGET /debug/items— dev-only: inspect in-memory found/lost arrays
- Matching strategy in
server.js:- Quick path: hidden mark + place + date rule (now fuzzy: exact, substring or token overlap) — fast and deterministic for demo seeds.
- Fallback path: compute embeddings for the combined texts and use cosine similarity (threshold 0.8).
- UI improvements (
src/App.jsx,src/styles.css) — a professional-looking form and two large CTAs (Report Lost / Report Found). Removed Tailwind CDN and added local CSS to avoid production warnings. - Added debug tooling:
GET /debug/itemsto inspect in-memory data?debug=trueon/lost-itemto return per-found-item hidden-checks and per-found-item embedding similarity scores when no match is found.
- Added
debug_similarity.js(small helper) used to compute normalization and embedding similarity between sample texts.
Requirements:
- Node.js >= 18
- npm
- Install dependencies
npm install- Optional: copy
.env.exampleto.envand add API keys
- Best: set
OPENAI_API_KEYfor higher-quality embeddings - Fallback: set
HF_API_KEY(Hugging Face) if you don't have OpenAI - If no keys are present, the server uses a deterministic local fallback embedding (useful for development/demo)
- Start the dev environment
This project has scripts for running backend + frontend together. The Vite client runs on port 3000 (configured in vite.config.js). The backend runs on port 5000.
# stop any previous node instances (optional, Windows)
taskkill /IM node.exe /F
# start server only (recommended for debugging)
node server.js
# or start client (in a separate terminal)
npm run client
# or run both in parallel (concurrently) - may spawn separate terminals
npm run dev- Open the UI in your browser
- Frontend: http://localhost:3000/
- Backend health: http://localhost:5000/health
- Debug items: http://localhost:5000/debug/items
-
POST /found-item
- Body (JSON): { name, itemName, description, place, dateFound, hiddenMark, image?, contactEmail }
- Response:
- If matches to existing lost reports: 200 { matchedLostEmails: [ ... ] }
- Else: 201 { added: true, foundItem: { ... } }
-
POST /lost-item
- Body (JSON): { name, itemName, description, place, dateLost, hiddenMark, image?, contactEmail }
- Query:
?debug=true(optional) — when provided and no match is found, the response includes adebugobject with hidden-checks and embedding similarities for each found item - Response:
- If matches: 200 { matchedFoundEmails: [ ... ] }
- Else: 201 { added: true, lostItem: {...}, debug?: { hiddenChecks, similarities } }
-
GET /debug/items
- Returns a slice of in-memory
foundItemsandlostItemsfor inspection.
- Returns a slice of in-memory
-
GET /health
- Returns
{ status: 'ok' }when server is running.
- Returns
- Combined text for embeddings:
itemName + description + place + hiddenMark(lowercased). - Quick/fuzzy hidden-mark match (fast path):
- Normalize both hiddenMark and place strings (lowercase, strip punctuation, collapse spaces).
- Hidden mark match if ANY of:
- exact equality
- substring containment (a contains b or b contains a)
- token overlap (share at least one token, e.g. both contain 'silver')
- AND place normalized equality
- AND the found date >= lost date
- If this passes for any found item, the server immediately returns the finder's email(s).
- Embedding fallback:
- Compute embeddings for combined texts (lost vs each found) and compute cosine similarity.
- Threshold: 0.8 (configurable in code).
- If similarity >= 0.8, it's a match.
Notes:
- The quick path ensures deterministic demo behavior with seeded items (e.g., hidden mark
silver-pendantwill matchsilver pendantand alsosilvertoken overlap). - The embedding route is used when quick path fails or hiddenMark is missing.
- To inspect found items and ensure the seeded demo item is present:
Invoke-RestMethod -Uri http://localhost:5000/debug/items | ConvertTo-Json -Depth 3- Submit a lost-item with debug flag to see why it didn't match:
$body = @{
name = 'Tharun raj'
itemName = 'wallet of colour black'
description = 'just balck wallet of leather'
place = 'mumbai'
dateLost = '2025-10-11'
hiddenMark = 'silver colour'
contactEmail = 'tharunraj923@gmail.com'
} | ConvertTo-Json
Invoke-RestMethod -Uri 'http://localhost:5000/lost-item?debug=true' -Method Post -Body $body -ContentType 'application/json' | ConvertTo-Json -Depth 4The debug output includes:
-
hiddenChecks: per-found-item whether the fuzzy hiddenMark/place check passed -
similarities: per-found-item cosine similarity score (useful to tune the threshold) -
You can run the helper script to compute a single similarity locally:
node debug_similarity.jsIt prints token normalization and the cosine similarity between the seeded found item and a sample lost submission.
The repo includes a seeded found item (first element in foundItems) that you can use when testing:
{
"id": 1,
"name": "Vikram",
"itemName": "Black Wallet",
"description": "Black leather wallet with ID card and a silver pendant",
"place": "Mumbai",
"dateFound": "2025-10-11",
"contactEmail": "vikram.finder@example.com",
"hiddenMark": "silver-pendant",
"claimed": false
}To trigger a deterministic demo match, submit a lost item with place: Mumbai and hiddenMark containing silver (for example silver colour or silver pendant). The quick path performs token overlap and should pick up such matches if the date constraint is satisfied.
Possible improvements you may want to add:
- Persist storage (JSON file, SQLite, or a small DB) so state survives restarts.
- Make the embedding similarity threshold configurable via an environment variable.
- Add a small admin page to view recent match attempts and per-item similarity scores.
- Integrate Tailwind properly via PostCSS / Tailwind CLI if you want Tailwind styles in production.
- Add image-based hashing or CLIP-based embeddings for image similarity.
If you'd like, I can implement any of the above next — tell me which and I’ll add it.
MIT
A full MVP of a Lost and Found platform with AI-powered matching and mock data, ready for frontend display and backend testing.
-
Backend:
- Node.js + Express server
- Mock data: 150 lost items, 150 found items with Indian-style names, descriptions, places, emails
- AI Matching:
- Primary: OpenAI embeddings for text similarity
- Fallback: Hugging Face embeddings (sentence-transformers/all-MiniLM-L6-v2)
- Matching conditions:
- Cosine similarity >= 0.8
- foundItem.dateFound >= lostItem.dateLost
- Route: GET
/matches→ returns[{lostItem, foundItem, similarityScore}]
-
Frontend:
- React app with functional components and hooks
- Fetches
/matchesendpoint from backend - Displays matched items in a responsive table with similarity scores
- Loading spinner while fetching data
- Error handling for backend failures or no matches
foundit/
├── .env # Environment variables (OpenAI API key)
├── server.js # Express server setup and /matches endpoint
├── mockData.js # Mock data for lost and found items
├── aiService.js # AI similarity computation with fallback logic
├── package.json # Project dependencies and scripts
├── index.html # Main HTML file
├── vite.config.js # Vite configuration
└── src/
├── main.jsx # React entry point
└── App.jsx # Main React component
-
Clone the repository:
git clone <repository-url> cd foundit
-
Install dependencies:
npm install
-
Set up environment variables:
- Rename
.env.exampleto.env - Add your OpenAI API key (preferred) or Hugging Face key as a fallback:
OPENAI_API_KEY=your_openai_api_key_here # or HF_API_KEY=your_hf_api_key_here
- Rename
-
Run the development server:
npm run dev
This will start the backend on port 5000 (by default) and the frontend via Vite.
-
Access the application:
- Frontend: http://localhost:3000
- Backend API: http://localhost:5000
- Matches endpoint: http://localhost:5000/matches
GET /matches- Returns matched lost and found items with similarity scoresGET /health- Health check endpoint
- Backend: Node.js with Express
- Frontend: React with Vite
- Styling: Tailwind CSS
- AI Services: OpenAI and Hugging Face
- Database integration (MongoDB/PostgreSQL)
- User authentication and profiles
- Reporting forms for lost/found items
- Email notifications
- Reward system
- Image upload and matching
- Mobile-responsive design
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a pull request
This project is licensed under the MIT License.
This project is now ready for deployment to Vercel. All necessary configuration files have been added and committed:
package.json- Project dependencies and scripts (now properly committed)vercel.json- Vercel deployment configuration (fixed routing for production)vite.config.js- Fixed port configurationDEPLOYMENT.md- Detailed deployment guide
- Go to Vercel
- Sign in/up
- Click "New Project"
- Import your GitHub repository (https://github.com/Tharun9247/FoundIt.git)
- Make sure the build settings are:
- Build Command:
npm run build - Output Directory:
dist
- Build Command:
- Deploy
The project will now build and deploy correctly without MIME/JSX errors.
For more detailed deployment instructions, see DEPLOYMENT.md.