A free website that helps people find blood donors fast when someone in their family is sick or has had an accident.
Imagine your aunt is in hospital and the doctor says "we need B-positive blood right now". You don't know who has B-positive blood. You panic. You call 30 friends. Hours pass.
LifeDrop fixes that. People who want to donate sign up once. They tell us their blood group and which city they live in. When someone needs blood, they search the website, find a matching donor, and message them. No middleman. No fees. No app to install.
The Bangla word for "blood needed" is "Rokto Lagbe" — that is the original name. LifeDrop is the same product in English.
- The big picture
- What a normal user does
- What's inside the project
- The technology behind it
- Run it on your computer
- Make a change and see it work
- Deploy it to the internet
- Common tasks
- If something breaks
- Glossary
┌────────────────┐ ┌────────────────┐
│ Donor Asha │ │ Patient Babu │
│ (B+ blood) │ │ needs B+ NOW │
└────────┬───────┘ └───────┬────────┘
│ 1. signs up once │ 2. searches
│ (phone + city + blood) │ "B+ in Dhaka"
▼ ▼
┌────────────────────────────────────────────────┐
│ LifeDrop Website │
│ │
│ Stores donor list Phone OTP login │
│ Search by blood+city Masked chat │
└─────────────────────────────────────────────────┘
│ 3. shows Asha as a match
│ Babu sends Asha a message
▼
┌────────────────────────────┐
│ Asha gets a notification. │
│ Asha + Babu chat in app. │
│ If Asha agrees, she goes │
│ to the hospital. │
└────────────────────────────┘
Three simple jobs the website does:
- Hold a list of people willing to donate blood (their blood group, city, phone).
- Let anyone search that list — "find B+ donors in Dhaka".
- Connect the patient and the donor through a private chat so the patient does not see the donor's real phone number until the donor agrees.
That's the whole thing. Everything else (the admin panel, the analytics, the notifications) is just helpers around those three jobs.
There are three kinds of people who use LifeDrop:
- Opens the website.
- Clicks Register.
- Types their phone number. Gets a 6-digit code by SMS. Types it back. (This is called "OTP" — One Time Password. It proves the phone is really theirs.)
- Picks blood group (A+, B+, O-, etc.), city, country.
- Done. Their card now shows up when other people search.
- Opens the website.
- Either searches directly ("find B+ in Chittagong") or posts a request ("My father needs O- urgently in Mumbai").
- Sees matching donor cards.
- Taps Message on a donor — chat opens. The donor's real phone is hidden until the donor chooses to share it.
- Logs into
/admin/. - Sees overall stats: how many donors, requests, cities.
- Can pause spammers, mark fake requests as closed, broadcast SMS alerts to all matching donors.
When you open the lifedrop folder, this is what you see:
lifedrop/
│
├── index.html ← the home page (search box + recent requests)
├── favicon.svg ← the tiny logo in the browser tab
├── style.css ← extra page styles (most styling comes from /shared/)
│
├── firebase-config.js ← keys + setup for Firebase (the cloud database)
├── firebase-messaging-sw.js ← lets the browser receive push notifications
│
├── cities.js ← list of supported cities (Dhaka, Mumbai, etc.)
│
├── rokto-core.js ← shared helpers (phone format, blood group logic)
├── rokto-shell.js ← top header, bottom menu, page navigation
├── rokto-shell.css ← styles for header / menu
├── rokto-landing.js ← the home page logic (search, recent requests)
├── rokto-onboarding.js ← the "first time? sign up here" flow
├── rokto-fcm.js ← push notifications (when a request matches you)
├── rokto-analytics.js ← anonymous usage tracking (no personal data)
├── rokto-i18n.js ← English / Bangla text strings
│
├── register/ ← the "Become a Donor" form
├── search/ ← the "Find Donors" page
├── request/ ← post an emergency blood request
├── chat/ ← private message between patient + donor
├── dashboard/ ← logged-in user's profile + their requests
├── admin/ ← admin-only page (stats + moderation)
├── about/ ← what is LifeDrop, mission, FAQ
├── donors/ ← public donor directory (SEO-friendly)
├── bn/ ← the Bangla version of the site
│
├── functions/ ← Firebase Cloud Functions (server-side code)
│ ├── index.js ← entry point — exports each function
│ ├── broadcast.js ← "alert all O+ donors in Sylhet" code
│ └── package.json ← Node.js dependencies (run `npm install` here)
│
├── scripts/ ← utility scripts (seed test donors, etc.)
│
├── shared/ ← copy of design system from teamzlab-tools
│ ├── css/tools.css ← buttons, cards, layout primitives
│ └── js/common.js ← header injector, toast pop-ups, helpers
│
├── branding/ ← logo, colors, fonts
│ ├── css/teamz-branding.css
│ └── fonts/poppins-*.woff2
│
├── firebase.json ← tells Firebase how to deploy this site
├── firestore.rules ← security rules (who can read/write what)
├── firestore.indexes.json ← speed-up hints for Firestore queries
├── .firebaserc ← which Firebase project this points to
│
├── SETUP.md ← Firebase setup walk-through (technical)
└── README.md ← this file (the one you're reading)
The two most important folders to remember:
functions/— server code. Runs on Google's servers. Sends SMS, runs cron jobs.shared/+branding/— design system. Don't edit these unless you really mean to. They are copied from the parent project (teamzlab-tools); future updates need to be re-copied.
| Word you'll hear | What it really is | Real-life analogy |
|---|---|---|
| HTML | The bones of a webpage. The text, buttons, forms. | Walls and rooms of a house. |
| CSS | Decoration. Colors, sizes, fonts. | Paint and furniture. |
| JavaScript (JS) | What makes the page do things when you click. | The electricity that turns lights on. |
| Firebase | Google's "ready-made backend". Database + login + storage in one box. | A pre-built kitchen — you don't build the oven, you just cook. |
| Firestore | The actual database inside Firebase. Stores donor records. | A giant filing cabinet in the cloud. |
| Firebase Auth | The login system. Phone OTP, email, etc. | The security guard at the gate. |
| Cloud Functions | Tiny programs that run on Google's servers when something happens. | A helper who runs to the post office for you. |
| OTP | One Time Password. The 6-digit SMS code. | A keycode for a hotel room — works once, then expires. |
| Firestore Rules | Text file that says "this person can read this, but not that". | Rules at a library: kids can read children's books, only librarians can edit them. |
Why Firebase and not a normal server? Because we are 1 person, not a 10-person team. Firebase handles login, scaling, SMS, push notifications. We just write the website. No DevOps. No 3 AM "the server is down" calls.
You need:
- A computer (Mac, Windows, or Linux).
- Python 3 (already on Mac/Linux; on Windows, install from python.org).
- Node.js 18 or newer (nodejs.org).
- Firebase CLI — install once with:
npm install -g firebase-tools - A Firebase account (free Google account works).
Open a terminal. Type:
git clone https://github.com/GkEmonGON/lifedrop.git
cd lifedropYou now have a folder called lifedrop with all the code.
The file firebase-config.js already has the connection keys for the live lifedrop-prod Firebase project. You can run the website immediately with these keys — but if you want your own private playground, do this:
- Go to https://console.firebase.google.com
- Click Add project, name it anything (e.g.
lifedrop-dev). - Inside the project: enable Authentication → Sign-in → Phone.
- Inside the project: enable Firestore Database in production mode (pick the closest region,
asia-south1for Bangladesh). - Click the
</>icon to "Add a Web App", copy thefirebaseConfigvalues. - Open
firebase-config.jsin your editor. Replace the values insideFIREBASE_CONFIG = { ... }with your new ones.
In the lifedrop folder, type:
python3 -m http.server 9090Then open this in your browser:
http://localhost:9090/
You should see the LifeDrop home page.
That's it. The website is now running on your laptop.
The folder functions/ is server code. You only need this if you want to deploy SMS broadcasts, scheduled cleanups, etc.
cd functions
npm install
cd ..To test functions locally, install Firebase CLI and run the emulator:
firebase login
firebase emulators:startThis starts a fake Firebase on your laptop — auth, database, functions all running locally. No internet, no SMS bill.
If you made your own Firebase project in Step 2, you need to upload the rules so Firestore knows who's allowed to read/write:
firebase use --add # pick your dev project, alias as "dev"
firebase deploy --only firestore:rules,firestore:indexesLet's say you want to change the home-page heading from "Find Blood Donors Near You" to "Save Lives. Donate Blood."
- Open
index.htmlin your editor. - Search for the old heading text. Change it.
- Save.
- Refresh your browser at
http://localhost:9090/. (No need to restart the server.) - You see your new heading.
That's the whole loop. Edit → Save → Refresh.
For files inside shared/ or branding/, the same — but remember those are copied from the parent project. If you change them here, those changes don't go back upstream automatically.
Once you have a Firebase project and firebase-config.js is filled in:
# 1. Tell Firebase which project this is for
firebase use lifedrop-prod
# 2. Deploy the website + rules + functions all at once
firebase deployOr selectively:
firebase deploy --only hosting # just the website
firebase deploy --only firestore:rules # just the security rules
firebase deploy --only functions # just the server codeAfter it finishes, Firebase prints a URL like https://lifedrop-prod.web.app. Open it. Your site is live.
For the real custom domain (lifedrop.com or a subdomain of tool.teamzlab.com), open the Firebase Console → Hosting → Add custom domain.
Open cities.js, add the new city to the right country's array. Save. Refresh.
- Open
rokto-i18n.js. - Each text string has an English version like
searchHeading: 'Find Blood Donors'. Add a new property for your language code, e.g.searchHeading_hi: 'रक्तदाता खोजें'(for Hindi). - Update the language switcher logic at the bottom of the file to load your new language.
Open https://console.firebase.google.com → pick your project → Firestore Database → Data tab. You'll see live collections: donors, blood_requests, rokto_stats, etc.
cd scripts
npm install firebase-admin
node seed-donors.js # if this script exists- Go to Firebase Console → Firestore →
donorscollection. - Find the spammer's document by phone number.
- Set
paused: true. Their card is hidden from search results immediately.
Open https://analytics.google.com (Google Analytics — rokto-analytics.js sends anonymous events: page views, search clicks, register completions). No personal data is sent.
| Problem | What's probably wrong | Fix |
|---|---|---|
| Page is blank / white | JavaScript error on load. | Open browser DevTools (F12) → Console tab. Read the red error. Usually a missing file or a typo. |
| "Firebase not configured" warning | firebase-config.js still has REPLACE_ME somewhere. |
Edit the file, paste real values from Firebase Console. |
| Phone OTP says "this domain is not authorized" | You forgot to add localhost to Firebase Auth's allowed domains. |
Firebase Console → Authentication → Settings → Authorized domains → Add localhost. |
| Search returns no results | Either no donors exist yet (seed test data), or Firestore index is still building. | Console → Firestore → Indexes tab. Wait until status is "Enabled". |
| Functions deploy fails with "billing not enabled" | Firebase Functions require the Blaze (pay-as-you-go) plan above the free tier. | Console → Upgrade. Free tier is generous: 2M invocations/month, 400K GB-seconds. |
| Push notifications don't work | Browser blocks notifications by default, or firebase-messaging-sw.js is not at the root. |
Make sure the file is at /firebase-messaging-sw.js (not in a sub-folder). Browser must be on HTTPS or localhost. |
| Styles look broken (no colors, no fonts) | The shared/ or branding/ folders are missing. |
Make sure the whole repo was cloned — those folders should exist at the root. |
Pre-commit hook complains about style.display = '' |
A code style rule. | Use showEl(el) or style.display = 'block' instead of empty string. |
- Repository / repo — a folder that Git is tracking. Like a project notebook with every page saved forever.
- Branch — an alternative version of the project. You can try things on a branch without breaking the main version.
- Commit — a saved snapshot. "Save game" for code.
- Pull request (PR) — "hey team, please review my branch and merge it into main".
- Submodule — a repo inside another repo. The outer repo just remembers a pointer ("at this commit"), not the actual files.
- API key — a long secret-ish string that lets your code talk to a service like Firebase. Some are public-safe (Firebase web keys), some must be hidden (Stripe secret keys).
- OTP — one-time SMS code, expires in minutes.
- Schema — the shape of your data. "A donor has a name (text), a blood group (one of 8 options), a city (text)".
- Index (database) — a shortcut that makes queries fast. Like the index at the back of a textbook.
- Cron job — a program that runs automatically on a schedule. "Every day at 3 AM, clean up old requests".
- Webhook — a URL that another service calls when something happens. "When someone pays, ping this URL".
- CDN — a copy of your website on hundreds of computers around the world so it loads fast for everyone.
- PII — personally identifiable information (phone, name, address). Treat it carefully. Don't log it. Don't email it. Don't post it on Twitter.
MIT License — Copyright (c) 2026 Teamz Lab LTD. Use it, fork it, ship it. Attribution appreciated, not required.
Teamz Lab — questions: hello@teamzlab.com
Welcome to the team. If anything in this README is confusing, that's a bug — open an issue and we'll rewrite the section.