Inspiration
Every night, restaurants and pantries throw away edible food while people nearby struggle with food insecurity. The gap isn’t always supply — it’s coordination. Surplus is time-sensitive: discovery is fragmented, pickup windows are short, and multi-stop logistics are hard to plan by hand. We wanted a phone-first loop that turns “we have leftovers” into “someone can claim them before they expire,” without charging kitchens for a cloud vision API.
Kentucky (and Louisville in particular) made that story concrete: a real city, real closing times, and a need for something demoable end-to-end in minutes.
What it does
SurplusLink connects donors (restaurants / pantries) with recipients who can pick up surplus before the window closes.
- Donor staff photograph leftover food.
- A local Food-101 classifier suggests title, categories, allergen heuristics, and quantity — staff always confirm.
- They publish a listing with portions and a pickup window.
- Recipients browse a live map + list, filter by distance / allergens, and claim portions.
- With multiple claims, SurplusLink builds an optimized pickup run (ordered stops + route polyline).
No payments, no delivery drivers — just discovery, reservation, and logistics for tonight’s surplus.
How I built it
- Frontend / app: Next.js 15 (App Router), TypeScript, React 19, Tailwind — mobile-first donor camera flow and recipient explore board.
- Auth & data: Auth.js (credentials + roles), Prisma, Supabase Postgres (pooler on Vercel + direct URL for migrations).
- Vision: Free local Food-101 ONNX via
@huggingface/transformers(no paid Gemini/OpenAI vision key), with offline / rate-limit fallback so listing still works when the model can’t load. - Maps & routing: Leaflet + OSM for the board; server-side nearest-neighbor / 2-opt stop ordering with OSRM polylines (straight-line fallback if OSRM is down).
- Ops: Expiry on read + expire route; transactional claims so portions can’t oversell; deployed on Vercel.
For a pickup run with $n$ stops, a greedy nearest-neighbor pass is $O(n^2)$; we optionally refine with 2-opt so the ordered itinerary stays fast enough for a demo ($< 2\text{s}$ for a handful of stops).
Challenges I ran into
- Vision on serverless: Running Food-101 / ONNX on Vercel is brittle (cold starts, package size, CPU). We invested in compression, quotas (
VISION_*), and a graceful manual-entry path instead of a hard failure. - Supabase networking: Vercel ↔ Postgres needed the transaction pooler for
DATABASE_URLand a separateDIRECT_URLfor Prisma push — easy to get wrong with IPv6-only direct hosts. - Ephemeral filesystems: Local
public/uploadsdoesn’t persist on Vercel, so production photos use data URLs inphotoUrl. - Trust & safety UX: Allergen suggestions are heuristics, not guarantees — every AI field is editable, and copy makes clear donors remain responsible for food handling.
- Race conditions: Concurrent claims required transactional stock decrements so two people can’t claim the last portion.
Accomplishments that I am proud of
- A full photo → listing → claim → multi-stop route demo in under ~3 minutes.
- Real computer-vision value without a paid cloud vision API.
- Dual-persona product (donor inbox + recipient explore) with privacy-minded details (no recipient PII on the public board; donor phone only after claim).
- Production deploy with seeded Louisville listings: https://kyhacks.vercel.app.
What I learned
- Food rescue is as much a logistics + UX problem as an ML problem — the human confirm step matters more than a perfect label.
- Shipping local ML in a hackathon means designing for degradation, not only for the happy path.
- Prisma + hosted Postgres on serverless is workable if you treat connection pooling as a first-class requirement.
- Small product choices (pickup windows, portion counts, claim cancel) do more for trust than flashy features.
What's next for SurplusLink
- Push / SMS reminders before pickup windows close.
- Stronger allergen and dietary tagging (still human-confirmed).
- Multi-city onboarding and pantry partnership workflows.
- Optional donor analytics: rescued portions over time, no-show rates.
- Explore native share sheets and offline-friendly listing drafts for kitchen staff on poor Wi‑Fi.
Built With
- auth.js
- hugging-face-transformers
- next.js
- node.js
- postgresql
- prisma
- react
- shadcn
- supabase
- tailwind-css
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.