Connecting food donors and NGOs to reduce food waste and power last-mile food redistribution.
- Overview
- How It Works
- Implemented Features
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables
- Available Scripts
- Data Model (Firestore)
- Notes
- License
Left2Lift is a role-based web app built to eliminate food waste at the last mile.
| Role | Who | What they do |
|---|---|---|
| π½οΈ Donor | Restaurants, events, caterers | Post surplus food pickups with location & time details |
| π€ NGO | Non-profit organizations | Discover nearby donations, claim them, and navigate to pickups |
The platform provides real-time updates, map-based discovery, and route optimization β making food redistribution fast and transparent.
1. Donor signs in β posts a new food donation
β
2. Donation saved to Firestore (status: available)
β
3. NGO dashboard receives real-time update
β
4. NGO claims a donation (status: claimed)
β
5. NGO navigates using in-app map route tools
β
6. Pickup completed and marked done (status: picked)
- Email/password sign-up and login via Firebase Authentication
- Role selection during signup: donor or ngo
- Role-based routing:
/donorβ Donor dashboard/ngoβ NGO dashboard
- Post a donation with:
- Title, description, quantity, and food type
- Best-before datetime and pickup window
- Address + GPS coordinates
- Google Places Autocomplete for address input
- Browser geolocation auto-fill as fallback
- Donor dashboard with live status summary cards:
- Total Β· Available Β· Claimed Β· Completed
- Real-time donation feed powered by Firestore listeners
- Toggle between Map View and List View
- Smart filters:
All AvailableΒ·Available NowΒ·ClaimedΒ·Mine - One-click claim flow with instant Firestore status sync
- Quick open route in Google Maps (
maps/dirβ fallback tomaps/search) - Live map markers with donation info windows
- Multi-pickup route planner:
- Optimized waypoints via Google Directions API
- ETA + distance display
- Step-by-step progress tracking and completion flow
- In-app notifications when new donations are posted
- Fully responsive dashboards for donor and NGO roles
- Status-aware donation cards with color-coded badges
- Modal-based posting and route flows
- Clean design powered by Tailwind CSS + Lucide icons
| Layer | Technology |
|---|---|
| βοΈ Frontend | React 18 + TypeScript |
| β‘ Build Tool | Vite 5 |
| π Routing | React Router DOM 7 |
| π¨ Styling | Tailwind CSS |
| πΌοΈ Icons | Lucide React |
| π Authentication | Firebase Authentication |
| ποΈ Database | Cloud Firestore (real-time) |
| π¦ Storage | Firebase Storage |
| πΊοΈ Maps | Google Maps JS API β Maps Β· Places Β· Directions Β· Geometry |
Left2Lift/
βββ public/
βββ src/
β βββ components/
β β βββ Auth/ # Login, Signup, Role selection
β β βββ Donor/ # Donor dashboard & post-donation forms
β β βββ NGO/ # NGO feed, map view, route planner
β β βββ Layout/ # Shared layout wrappers, navbar
β βββ config/
β β βββ firebase.ts # Firebase app initialization
β βββ hooks/
β β βββ useAuth.ts # Auth state & role management
β β βββ useGoogleMaps.ts # Maps API loader & helpers
β βββ types/
β β βββ index.ts # Shared TypeScript interfaces
β βββ App.tsx # Root component & route definitions
βββ .env # Environment variables (not committed)
βββ .env.example # Template for environment setup
βββ index.html
βββ package.json
βββ tailwind.config.ts
βββ tsconfig.json
βββ vite.config.ts
- Node.js v18 or higher
- npm v9+ (or yarn / pnpm)
- A Firebase project β Create one here
- A Google Cloud project with Maps APIs enabled β Cloud Console
git clone https://github.com/Tejas164321/Left2Lift.git
cd Left2Liftnpm installcp .env.example .env
# Open .env and fill in your Firebase + Google Maps keysnpm run devOpen the local URL shown by Vite β typically http://localhost:5173
Create a .env file in the project root (same level as package.json):
# Firebase Configuration
VITE_FIREBASE_API_KEY=your_firebase_api_key
VITE_FIREBASE_AUTH_DOMAIN=your-project-id.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
VITE_FIREBASE_STORAGE_BUCKET=your-project-id.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_id
# Google Maps
VITE_GOOGLE_MAPS_API_KEY=your_google_maps_api_key| Variable | Where to get it |
|---|---|
VITE_FIREBASE_* |
Firebase Console β Project Settings β Your Apps β Web App SDK Config |
VITE_GOOGLE_MAPS_API_KEY |
Google Cloud Console β APIs & Services β Credentials β Create API Key |
Enable all of the following in your Google Cloud project:
- β Maps JavaScript API
- β Places API
- β Directions API
- β Geometry Library (loaded via Maps JS API)
π‘ Tip: Restrict your API key by HTTP referrer in production to prevent unauthorized usage.
npm run dev # Start development server with hot reload
npm run build # Production build β outputs to dist/
npm run preview # Preview the production build locally
npm run lint # Run ESLint across the project| Field | Type | Description |
|---|---|---|
email |
string |
User's email address |
displayName |
string |
Display name |
role |
"donor" | "ngo" |
User role assigned at signup |
createdAt |
timestamp |
Account creation time |
| Field | Type | Description |
|---|---|---|
donorId |
string |
UID of the posting donor |
donorName |
string |
Display name of the donor |
title |
string |
Donation title |
description |
string |
Description of the food |
quantity |
string |
Amount / portions available |
foodType |
string |
Category (e.g. cooked, packaged) |
expiryTime |
timestamp |
Best-before datetime |
pickupWindow |
string |
Available pickup time range |
location.lat |
number |
Latitude coordinate |
location.lng |
number |
Longitude coordinate |
location.address |
string |
Human-readable address |
status |
"available" | "claimed" | "picked" | "expired" |
Current donation status |
claimedBy |
string? |
NGO UID (set when claimed) |
claimedByName |
string? |
NGO display name (set when claimed) |
claimedAt |
timestamp? |
Timestamp of when donation was claimed |
createdAt |
timestamp |
When the donation was originally posted |
β οΈ Firestore Indexes: Combinedwhere + orderByqueries used in dashboards may require composite indexes. Firestore will log a direct link in your browser console to create them if they are missing.
- Some UI labels may still reference older naming (e.g.
"ZeroWaste DineMap"text in a few places). These are cosmetic leftovers and do not affect any core functionality. - Configure Firestore Security Rules before deploying to production to restrict read/write access by user role.
- The Google Maps API key should be HTTP referrer restricted in production environments.
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create a feature branch β
git checkout -b feature/your-feature-name - Commit your changes β
git commit -m 'feat: describe your change' - Push to the branch β
git push origin feature/your-feature-name - Open a Pull Request
This project is licensed under the MIT License β see the LICENSE file for details.
Made with β€οΈ to reduce food waste, one pickup at a time. β Star this repo if you find it helpful!