An eco-conscious mobile app that rewards users for taking real environmental action.
SeaScore (also called SaveEarth) motivates users to reduce plastic waste and protect the oceans. Users complete real-world sustainability challenges, upload proof, earn points, unlock rewards, and engage with a community of eco-active people.
Goal: Make sustainability fun, social, and rewarding. 🌱
Frontend: React 18 + TypeScript + Vite (a web app styled as a phone UI — not React Native)
UI: Tailwind CSS + Radix UI
Backend: Node.js + Express
Machine Learning: Xenova OWLv2 (Zero-Shot Detection)
Auth / Database: Firebase Authentication + Realtime Database
Deployment: Docker + Docker Compose
Uploads: multer
Model Runtime: @xenova/transformers
Design: Figma UI
- Node.js + npm
- Docker (optional but recommended)
git clone https://github.com/SNBest1/SaveEarth.git cd SaveEarth
- Install dependencies
Client:
npm install
Server:
cd src/server npm install cd ../..
-
Download the ML model node src/server/download-model.mjs
-
Run locally npm start
Make sure the model is downloaded first:
node src/server/download-model.mjs
docker-compose up -d
App will be available at: http://localhost:3000
┌─────────────────────────────────────────────┐
│ Browser — React 18 + Vite (phone-framed UI) │
│ │
│ Onboarding → Challenges → UploadProof → │
│ ValidationResult → Celebration → Rewards │
└──────────┬──────────────────────┬───────────┘
│ │
│ POST /validate-image │ auth + data
│ (multipart: image, │
│ candidate labels) ▼
│ ┌──────────────────┐
▼ │ Firebase │
┌────────────────────┐ │ Auth + Realtime │
│ Express │ │ Database │
│ src/server/ │ └──────────────────┘
│ │
│ multer → temp file │
│ @xenova/transformers
│ Xenova/owlv2- │
│ base-patch16 │
│ zero-shot object │
│ detection │
│ │
│ → { detected, │
│ score } │
└────────────────────┘
runs locally on CPU
model downloaded via
download-model.mjs
Because there is no training data for "picked up litter", and never will be.
The obvious approach is a classifier trained per challenge. That needs a labelled dataset of proof photos for every challenge type — which does not exist, could not be collected during a hackathon, and would have to be rebuilt every time someone adds a challenge.
OWLv2 does open-vocabulary detection: it takes the candidate labels as text at inference time. Adding a new challenge means writing a new label string. No retraining, no data collection, no model artifacts per challenge. The challenge system and the vision model stay completely decoupled — which is the property that makes the app extensible by non-ML contributors.
What it costs:
- Accuracy. A model trained on actual proof photos would beat zero-shot on any single fixed challenge. Zero-shot trades peak accuracy for coverage.
- Latency. OWLv2 runs on CPU here; inference is seconds, not milliseconds. Acceptable for a one-off "submit your proof" action, not for anything live.
- Gameability. Detecting that a bottle is present is not the same as verifying someone recycled it. The model confirms the photo is plausible; it is not fraud detection, and the README should not pretend otherwise.
Why run the model locally rather than call a vision API? No per-call cost, no
key to distribute, and the app keeps working offline once
download-model.mjs has run. The tradeoff is a large model download on first
setup and CPU inference, which is why models/ is gitignored and fetched
separately.
Users sign up and log in using Firebase Auth.
Each challenge includes:
- A description
- A category (example: recycling, cleanup)
- A point value
Users upload a photo to complete challenges. The backend uses a zero-shot model to verify the action before awarding points.
- Model:
Xenova/owlv2-base-patch16 - Can detect objects based on text prompts
- Does not require retraining for each challenge
Users collect stamps for completed challenges and see their total impact.
Points can be exchanged for rewards.
Real-time feed showing completed challenges across the community.
Users can join teams and compete on scoreboards.
Educational content for reducing plastic waste and protecting the oceans.
- User uploads image
- Server receives image + challenge keywords
- ML model runs zero-shot detection
- The model returns a confidence score
- If above threshold → challenge is marked complete
- Express.js API
multerhandles file uploads@xenova/transformersloads ML model- Singleton pattern ensures performance
- Script:
src/server/download-model.mjscaches model locally
- Efficient ML inference on low-power devices
- Handling edge case submissions
- Balancing strictness vs usability in validation
- Optimizing performance and model load times
- Train a custom sustainability-focused model
- AI-based suggestions & challenge personalization
- Offline mode
- Public sharing of completed challenges
- Better reward marketplace
- Brand partnerships for eco-rewards
- Carbon impact tracker
- Team chat system
Figma UI: https://www.figma.com/design/8LZeuVJY5Hvdr1lU6qBlnK/EcoPassport-Mobile-App-UI
Aditya, Nipun Saini, and team — built at a hackathon (Honorable Mention). Forked from Aditya9246/SaveEarth.