Built for SE3090 Assignment 2 — Mini Hackathon (MERN Stack + Google Gemini AI)
In Sri Lanka, hospitality, bakeries, and food service establishments account for roughly 25% of total food waste, with thousands of kilograms of wholesome, freshly prepared food discarded at end-of-day closing hours. Concurrently, vulnerable communities, orphanages, elders' homes, low-income families, and animal welfare shelters face acute daily shortages of edible food and animal feed.
- Lack of Rapid Channels: Food businesses have no instant, zero-friction medium to notify local recipients when surplus food remains unsold at closing time.
- Coordination Asymmetry: Community organizations, charity workers, and shelter volunteers cannot track real-time food availability, quantities, or pickup locations.
- Time Criticality: Prepared food is perishable; manual phone calls and ad-hoc word-of-mouth coordination fail to beat the end-of-day expiration window.
FoodShare LK digitizes and streamlines surplus food rescue:
- Donors (Hotels, Bakeries, Restaurants, Households) can list surplus items in under 60 seconds with pickup time limits, quantities, and intended beneficiaries (human vs. animal).
- Recipients (Individuals, NGOs, Elders' Homes, Animal Shelters) discover available food instantly through localized search and multi-parameter filters.
- Conflict-Free One-Click Claiming locks the listing in real-time, preventing wasted trips and connecting claimant and donor directly.
- Grounded AI Donation Assistant (Google Gemini) analyzes live, real-time database snapshots to advise donors on which categories and areas have the most critical shortage of donations.
| Feature | Description | Target Role |
|---|---|---|
| Frictionless Role Switching | Instant toggle between Donor, Recipient, and Guest modes stored in reactive state context — no tedious account creation or login walls during crisis redistribution. | All |
| Rapid Donation Publishing | Form with 10 strict validation rules (PRD §12), automated Sri Lankan phone number validation (+94 or 0 prefix), and pickup window verification. |
Donor |
| My Listings Dashboard | Live listing control room allowing donors to monitor their active posts, modify pickup details, cancel listings, or manually flag donations as claimed. | Donor |
| Multi-Filter Discovery Feed | Responsive card grid with instant client/server filtering across Food Item / Type, Location / Town, and Beneficiary Target (people, animals, both). |
Recipient |
| Atomic Claiming Engine | Real-time state transition (available → claimed) with concurrency guard (HTTP 409 Conflict if claimed simultaneously), capturing claimant organization details and unlocking direct contact numbers. |
Recipient |
| Grounded AI Donation Assistant | Embedded floating assistant powered by Google Gemini (gemini-3.6-flash), dynamically injected with live MongoDB need-aggregations to provide real-time, data-backed guidance on where donations are needed most. |
Donor / Guest |
| Live Impact Analytics | Dedicated platform stats endpoint (/api/v1/stats) serving aggregated counts for total donations, claimed food packages, and active opportunities. |
Public / Guest |
┌─────────────────────────────────────────────────────────────┐
│ Client Browser │
│ React 19 + TypeScript + Vite + Modern CSS3 │
└──────────────────────────────┬──────────────────────────────┘
│ HTTPS / JSON REST API
▼
┌─────────────────────────────────────────────────────────────┐
│ Node.js / Express 5 API Server │
│ Routes, Validation Middlewares, Error Handlers │
└──────────────┬──────────────────────────────┬───────────────┘
│ Mongoose ODM │ Google GenAI REST
▼ ▼
┌──────────────────────────────┐ ┌────────────────────────────┐
│ MongoDB Atlas (Cloud) │ │ Google Gemini AI API │
│ `listings` collection & │ │ Grounded Advice Engine │
│ Compound Text Indexes │ │ (gemini-3.6-flash) │
└──────────────────────────────┘ └────────────────────────────┘
- Framework: React 19 (
react,react-dom) with TypeScript 6 - Routing: React Router v7 (
react-router-dom) - HTTP Client: Axios
- Build Tooling: Vite 8 with
@vitejs/plugin-react&@rolldown/plugin-babel - Styling: CSS3 Variables, Responsive Flexbox & Grid, Mobile-First layout
- Runtime: Node.js v18+ (CommonJS)
- Web Framework: Express 5 (
express@^5.2.1) - Database ODM: Mongoose 9 (
mongoose@^9.9.4) - Cross-Origin & Config:
cors,dotenv - Generative AI: Google Gemini API (
gemini-3.6-flash)
- Host: MongoDB Atlas
- Key Models:
Listing(with compound text indexes onfoodItemandlocation, ascending index onstatusandcreatedAt)
demo frontend :- https://sef-mini-hackerthon-two.vercel.app
demo backend :- https://sef-mini-hackerthon-1.onrender.com/
Base URL: /api/v1 (with fallback support on /api)
| Method | Route | Description | Request Body / Parameters | Success Code |
|---|---|---|---|---|
GET |
/health |
Server health check | None | 200 OK |
GET |
/listings |
Query all listings with optional filters | Query: ?foodType=...&location=...&forWhom=...&status=... |
200 OK |
GET |
/listings/:id |
Get single listing by ID | URL param: id |
200 OK |
POST |
/listings |
Create a new surplus food listing | JSON body (see schema below) | 201 Created |
PATCH |
/listings/:id |
Partially update listing details | JSON body with updated fields | 200 OK |
PATCH |
/listings/:id/claim |
Claim an available food listing | { "claimedBy": "Community Volunteer Name/Org" } |
200 OK |
DELETE |
/listings/:id |
Permanently cancel / delete listing | URL param: id |
200 OK |
GET |
/stats |
Aggregate donation and claiming counts | None | 200 OK |
POST |
/assistant |
Chat with Gemini AI grounded on live data | { "messages": [{ "role": "user", "text": "..." }] } |
200 OK |
{
"donorName": "Perera Bakery",
"donorType": "bakery",
"foodItem": "Fresh Bread Loaves",
"quantity": 25,
"quantityUnit": "loaves",
"forWhom": "both",
"location": "Ratnapura Town",
"pickupWindowStart": "2026-09-04T18:30:00.000Z",
"pickupWindowEnd": "2026-09-04T21:30:00.000Z",
"contactNumber": "0771234567",
"notes": "Freshly baked today, packed in clean boxes."
}{
"success": false,
"errors": [
{ "field": "quantity", "message": "Quantity must be a positive number." },
{ "field": "contactNumber", "message": "Enter a valid Sri Lankan phone number, e.g. 0771234567." }
]
}Mini HackerThon/
├── README.md # Root project documentation
├── LICENSE # Apache License 2.0
├── docs/ # Specification & Engineering Artifacts
│ ├── PRD.md # Product Requirements Document
│ ├── plan.md # 4-member task allocation & hackathon schedule
│ ├── FOODSHARE_DFD.md # Data Flow Diagrams (Context, L1, L2 + Dictionary)
│ └── FOODSHARE_SRS.md # IEEE 830 Software Requirements Specification
├── backend/ # Node.js + Express + Mongoose Backend
│ ├── .env.example # Environment variables template
│ ├── package.json # Backend scripts and dependencies
│ ├── server.js # HTTP server bootstrap & DNS configuration
│ ├── src/
│ │ ├── app.js # Express application configuration & middleware pipeline
│ │ ├── config/db.js # MongoDB Atlas connection handler
│ │ ├── controllers/ # Request handlers (listings, health, assistant)
│ │ ├── middlewares/ # Validation & centralized error handlers
│ │ ├── models/Listing.js # Mongoose listing schema & text indexes
│ │ ├── routes/ # Modular Express routing definitions
│ │ └── seed/seedListings.js # 12 pre-built realistic Sri Lankan listings
│ └── test/core-api.test.js # Automated core API unit/integration tests
└── frontend/ # React 19 + TypeScript + Vite Client
├── package.json # Client scripts and dependencies
├── vite.config.ts # Vite configuration & proxy settings
├── index.html # Single Page Application HTML root
└── src/
├── App.tsx # Root component & Route declarations
├── main.tsx # React DOM mounting
├── api/ # Axios service integrations (listingsApi, assistantApi)
├── components/ # Reusable UI components (Navbar, FilterBar, ListingCard, RoleSwitcher, DonationAssistant)
├── context/RoleContext.tsx # Lightweight session role state management
├── pages/ # Views (Home, DonateForm, MyListings, BrowseListings, ListingDetail, ClaimConfirmation, About, NotFound)
├── styles/ # CSS stylesheets & theme variables
└── types/ # TypeScript interfaces & enums
- Node.js: v18.0.0 or higher (
node -v) - npm: v9.0.0 or higher (
npm -v) - MongoDB Atlas Cluster: Free M0 cluster connection URI
- Google Gemini API Key: (Optional for AI assistant) Obtain from Google AI Studio
git clone https://github.com/pasan-wijekoon/SEF-Mini-Hackerthon.git
cd SEF-Mini-Hackerthon- Navigate to backend directory:
cd backend - Install dependencies:
npm install
- Create environment file:
copy .env.example .env
- Configure
.envvalues:PORT=5000 MONGO_URI=mongodb+srv://<username>:<password>@cluster0.mongodb.net/foodshare?retryWrites=true&w=majority GEMINI_API_KEY=your_gemini_api_key_here GEMINI_MODEL=gemini-3.6-flash
- Seed initial realistic dataset (12 Sri Lankan food listings):
npm run seed
- Start backend development server:
The backend will boot on
npm run dev
http://localhost:5000.
- Open a new terminal and navigate to frontend directory:
cd frontend - Install dependencies:
npm install
- Start frontend development server:
The application will be accessible at
npm run dev
http://localhost:5173.
Execute automated backend tests verifying seed data integrity, middleware validation, and error shape contracts:
cd backend
npm testExecute frontend TypeScript check and production build:
cd frontend
npm run buildThe seed dataset (backend/src/seed/seedListings.js) populates 12 realistic Sri Lankan surplus listings to demonstrate varied locations, food types, and beneficiary groups:
| Donor Name | Donor Type | Food Item | Quantity | Beneficiary | Location |
|---|---|---|---|---|---|
| Perera Bakery | Bakery | Fresh Bread Loaves | 20 loaves | Both | Ratnapura Town |
| Green Leaf Hotel | Hotel | Rice & Curry Packets | 15 packets | People | Colombo 6 |
| Sunrise Restaurant | Restaurant | Cooked Veg Trimmings & Rice | 8 kg | Animals | Kandy |
| Mount Bakers | Bakery | Cakes & Pastries | 30 items | People | Nugegoda |
| Ocean View Hotel | Hotel | Buffet Surplus (Curries & Hoppers) | 12 kg | Both | Galle Fort |
| Heritage Cafe | Restaurant | String Hoppers with Sodi | 50 items | People | Kurunegala |
| City Central Bakery | Bakery | Buns and Savoury Rolls | 25 items | People | Negombo |
| Golden Spoon Caterers | Other | Fried Rice & Devilled Chicken | 18 plates | People | Maharagama |
| Paws & Tails Care Community | Household | Meat Broth & Rice Mix | 10 kg | Animals | Dehiwala |
| Southern Palms Resort | Hotel | Assorted Breads & Fruits | 15 kg | Both | Bentota |
| Lakeside Dining | Restaurant | Boiled Lentils, Rice & Bread | 14 kg | Animals | Nuwara Eliya |
| Suburban Kitchen | Household | Vegetable Rice Packets | 8 packets | People | Malabe |
In adherence to the SE3090 Mini Hackathon guidelines, responsibilities were evenly distributed across frontend and backend tracks:
| Team Member | Student ID | Track & Role | Modules Owned & Contributions |
|---|---|---|---|
| Member 1 | IT24102690 | Frontend — Donor Track | Home.tsx, DonateForm.tsx (all 10 validation rules), MyListings.tsx, Navbar.tsx, RoleSwitcher.tsx, RoleContext.tsx. |
| Member 2 | Yashodha | Frontend — Recipient Track | BrowseListings.tsx (search & multi-filter), ListingDetail.tsx, ClaimConfirmation.tsx, About.tsx, NotFound.tsx, ListingCard.tsx, FilterBar.tsx. |
| Member 3 | Pasan Wijekoon | Backend — Core API & Data | MongoDB Atlas schema (Listing.js), compound text indexing, POST /listings, GET /listings, GET /listings/:id, validateListing.js middleware, seedListings.js, core-api.test.js. |
| Member 4 | Ransidu Subasinghe | Backend — Actions & AI Ops | PATCH /listings/:id, PATCH /listings/:id/claim, DELETE /listings/:id, /stats endpoint, errorHandler.js, Google Gemini AI integration (assistantController.js, DonationAssistant.tsx), deployment configs. |
In compliance with hackathon assessment requirements, AI tools were leveraged to accelerate boilerplate creation, formulate realistic test data, and refine schema validation:
- Google Gemini Flash (
gemini-3.6-flash): Powering the in-app Donation Assistant to analyze real-time database demand snapshots and advise donors. - Claude / Antigravity CLI: Assisting with architecture design, DFD/SRS technical documentation generation, and error schema standardization.
- "Draft a Mongoose schema for a Sri Lankan surplus food platform with enum constraints for donor types, food units, and beneficiary targets (people vs animals)."
- "Implement an Express validation middleware that tests for valid Sri Lankan telephone numbers starting with +94 or 0 and rejects pickup window end dates that precede start dates."
- "Construct an AI prompt injection function that queries MongoDB for unclaimed food counts by location and category to ground Gemini recommendations in real inventory data."
This project is licensed under the Apache License 2.0 — see the LICENSE file for details.