A full-stack blood donor discovery and donor management platform focused on Bangladesh. RedBridge helps users quickly find approved blood donors by blood group and location, while giving administrators the tools to review and moderate donor registrations.
RedBridge is designed to reduce the time required to connect blood seekers with available donors.
Purpose:
- Make blood donor search faster and location-aware.
- Provide a trusted donor directory through an admin approval workflow.
- Offer a simple and accessible interface for both donors and seekers.
Main features:
- Firebase-based user authentication.
- Donor profile creation with blood group and detailed location.
- Admin moderation (approve/reject/delete donor profiles).
- Public donor search with filters.
- Bangladesh locations support (division, district, upazila).
Expected users:
- Blood seekers and patient families.
- Voluntary blood donors.
- University/project admins or moderators.
- React 19
- Vite 7
- React Router DOM 7
- Axios
- Tailwind CSS 4
- DaisyUI
- React Hot Toast
- SweetAlert2
- React Icons
- Node.js
- Express 4
- TypeScript 5
- Zod (request validation)
- Helmet (security headers)
- CORS
- express-rate-limit
- MongoDB
- Mongoose
- Firebase Authentication (client)
- Firebase Admin SDK (server-side token verification)
- Role-based access control (
admin,donor)
- ESLint
- tsx
- Vercel (frontend + backend deployments)
- Node.js 20+ (recommended)
- npm 10+
- MongoDB (local or cloud instance)
- Firebase project with Authentication enabled
git clone <your-repository-url>
cd RedBridgecd Client-Side
npm install
cd ../Server-Side
npm installCreate .env in Server-Side:
NODE_ENV=development
PORT=5000
MONGODB_URI=mongodb://localhost:27017/blood-donation-finder
FIREBASE_PROJECT_ID=your-firebase-project-id
FIREBASE_CLIENT_EMAIL=your-firebase-client-email
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
CORS_ORIGIN=http://localhost:5173,http://localhost:3000Create .env in Client-Side:
VITE_API_BASE_URL=http://localhost:5000
VITE_ADMIN_EMAILS=admin1@example.com,admin2@example.com
VITE_FIREBASE_API_KEY=your-api-key
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
VITE_FIREBASE_APP_ID=your-app-idProduction note:
- In Vercel, set
VITE_API_BASE_URLto your deployed backend URL (for examplehttps://your-backend.vercel.app). - Do not keep
VITE_API_BASE_URL=http://localhost:5000for production builds. - Optionally set
VITE_ADMIN_EMAILS(comma-separated) so admin role fallback still works if role API is temporarily unavailable.
Backend deployment note:
- In Vercel (Server-Side project), set
MONGODB_URI(orMONGODB_URL/DATABASE_URL) to your MongoDB Atlas connection string. - Also set
CORS_ORIGINto your frontend domain (for examplehttps://redbridgediu.vercel.app).
Start backend:
cd Server-Side
npm run devStart frontend in a second terminal:
cd Client-Side
npm run devDefault local URLs:
- Frontend:
http://localhost:5173 - Backend health:
http://localhost:5000/health
Backend:
npm run build
npm run start
npm run lint
npm run seedFrontend:
npm run build
npm run preview
npm run lint- Local backend root:
http://localhost:5000 - API prefix:
/api - Effective local API base:
http://localhost:5000/api
Protected endpoints require Firebase ID token:
Authorization: Bearer <firebase_id_token>Authorization rules:
- Public: no token needed.
- Authenticated: valid Firebase token required.
- Admin only: valid token and user role must be
admin.
Success response:
{
"success": true,
"message": "Operation successful",
"data": {}
}Paginated response:
{
"success": true,
"message": "Data retrieved successfully",
"meta": {
"page": 1,
"limit": 10,
"total": 52,
"totalPages": 6
},
"data": []
}Error response:
{
"success": false,
"code": "INTERNAL_ERROR",
"message": "Something went wrong",
"details": "optional in development",
"data": null
}Access: Public
Success response example:
{
"success": true,
"message": "Blood Donation Finder API is running",
"data": {
"timestamp": "2026-03-30T12:00:00.000Z",
"uptime": 1234.56
}
}Access: Public Purpose: Create user record after Firebase sign-in.
Request body example:
{
"name": "Rahim Uddin",
"email": "rahim@example.com",
"photoURL": "https://example.com/avatar.jpg",
"phone": "01712345678",
"address": "Dhaka",
"bio": "Regular blood donor"
}Success response example (201):
{
"success": true,
"message": "User created successfully",
"data": {
"_id": "660a1b2c3d4e5f6a7b8c9d0e",
"name": "Rahim Uddin",
"email": "rahim@example.com",
"role": "donor"
}
}Access: Admin only Purpose: Get users list.
Query parameters:
page(optional, positive integer)limit(optional, positive integer, max 100)
Success response example:
{
"success": true,
"message": "Users retrieved successfully",
"meta": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1
},
"data": [
{
"_id": "660a1b2c3d4e5f6a7b8c9d0e",
"name": "Rahim Uddin",
"email": "rahim@example.com",
"role": "donor"
}
]
}Access: Public Purpose: Get a single user by email.
Success response example:
{
"success": true,
"message": "User retrieved successfully",
"data": {
"_id": "660a1b2c3d4e5f6a7b8c9d0e",
"name": "Rahim Uddin",
"email": "rahim@example.com",
"role": "donor"
}
}Access: Public Purpose: Update user profile fields by email.
Request body example:
{
"name": "Rahim Uddin",
"photoURL": "https://example.com/new-avatar.jpg",
"phone": "01812345678",
"address": "Dhaka, Bangladesh",
"bio": "Available for emergency donation",
"isVerified": true,
"lastLogin": "2026-03-30T09:20:00.000Z"
}Success response example:
{
"success": true,
"message": "User updated successfully",
"data": {
"_id": "660a1b2c3d4e5f6a7b8c9d0e",
"email": "rahim@example.com"
}
}Access: Admin only Purpose: Change user role.
Request body example:
{
"role": "admin"
}Success response example:
{
"success": true,
"message": "User role updated successfully",
"data": {
"_id": "660a1b2c3d4e5f6a7b8c9d0e",
"role": "admin"
}
}Access: Authenticated Purpose: Create donor profile with pending status.
Request body example:
{
"bloodType": "O+",
"location": {
"division": "Dhaka",
"district": "Dhaka",
"upazila": "Dhanmondi",
"area": "Road 27"
},
"phone": "01712345678",
"availability": true
}Success response example (201):
{
"success": true,
"message": "Donor profile created successfully. Awaiting admin approval.",
"data": {
"_id": "660b2c3d4e5f6a7b8c9d0e1f",
"bloodType": "O+",
"status": "pending"
}
}Access: Public Purpose: Search approved donors.
Query parameters:
bloodType(A+, A-, B+, B-, O+, O-, AB+, AB-)divisiondistrictupazilapage(optional)limit(optional, max 100)
Success response example:
{
"success": true,
"message": "Donors retrieved successfully",
"meta": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1
},
"data": [
{
"_id": "660b2c3d4e5f6a7b8c9d0e1f",
"bloodType": "O+",
"status": "approved"
}
]
}Access: Admin only Purpose: Get pending donor requests.
Query parameters:
page(optional)limit(optional, max 100)
Success response example:
{
"success": true,
"message": "Pending donor requests retrieved successfully",
"meta": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1
},
"data": [
{
"_id": "660b2c3d4e5f6a7b8c9d0e1f",
"status": "pending"
}
]
}Access: Public Purpose: Get donor details by id.
Success response example:
{
"success": true,
"message": "Donor retrieved successfully",
"data": {
"_id": "660b2c3d4e5f6a7b8c9d0e1f",
"bloodType": "O+",
"location": {
"division": "Dhaka",
"district": "Dhaka",
"upazila": "Dhanmondi",
"area": "Road 27"
},
"phone": "01712345678",
"availability": true,
"status": "approved"
}
}Access: Authenticated (owner only) Purpose: Update donor profile.
Request body example:
{
"bloodType": "A+",
"location": {
"district": "Gazipur"
},
"phone": "01812345678",
"availability": false
}Success response example:
{
"success": true,
"message": "Donor profile updated successfully",
"data": {
"_id": "660b2c3d4e5f6a7b8c9d0e1f",
"bloodType": "A+"
}
}Access: Admin only Purpose: Remove donor profile.
Success response example:
{
"success": true,
"message": "Donor profile deleted successfully",
"data": {
"_id": "660b2c3d4e5f6a7b8c9d0e1f"
}
}Access: Admin only Purpose: Approve donor profile.
Request body: none
Success response example:
{
"success": true,
"message": "Donor approved successfully",
"data": {
"_id": "660b2c3d4e5f6a7b8c9d0e1f",
"status": "approved"
}
}Access: Admin only Purpose: Reject donor profile.
Request body: none
Success response example:
{
"success": true,
"message": "Donor rejected successfully",
"data": {
"_id": "660b2c3d4e5f6a7b8c9d0e1f",
"status": "rejected"
}
}Access: Public Purpose: Get full Bangladesh location tree.
Success response example:
{
"success": true,
"message": "Full location tree retrieved successfully",
"data": [
{
"division": "Dhaka",
"districts": [
{
"district": "Dhaka",
"upazila": ["Dhanmondi", "Gulshan"]
}
]
}
]
}Access: Public Purpose: Get all divisions.
Success response example:
{
"success": true,
"message": "Divisions retrieved successfully",
"data": [
{
"division": "Dhaka",
"divisionbn": "ঢাকা"
}
]
}Access: Public Purpose: Get districts and upazilas for a division.
Success response example:
{
"success": true,
"message": "Districts of Dhaka retrieved successfully",
"data": [
{
"district": "Dhaka",
"upazila": ["Dhanmondi", "Mirpur"]
}
]
}Access: Public Purpose: Get upazilas by district.
Success response example:
{
"success": true,
"message": "Upazilas of Dhaka retrieved successfully",
"data": ["Dhanmondi", "Mirpur"]
}Common API error examples:
400 Bad Request
{
"success": false,
"code": "INVALID_DATA",
"message": "Invalid request data",
"data": null
}401 Unauthorized
{
"success": false,
"code": "UNAUTHORIZED",
"message": "No authorization token provided",
"data": null
}403 Forbidden
{
"success": false,
"code": "FORBIDDEN",
"message": "Access denied",
"data": null
}404 Not Found
{
"success": false,
"code": "NOT_FOUND",
"message": "Resource not found",
"data": null
}409 Conflict
{
"success": false,
"code": "DUPLICATE_FIELD",
"message": "Duplicate value found",
"data": null
}429 Too Many Requests
{
"success": false,
"message": "Too many requests. Please try again later.",
"error": "Too many requests. Please try again later."
}500 Internal Server Error
{
"success": false,
"code": "INTERNAL_ERROR",
"message": "Internal Server Error",
"data": null
}RedBridge/
|-- README.md
|-- Client-Side/
| |-- package.json
| |-- vite.config.js
| |-- vercel.json
| |-- src/
| |-- main.jsx
| |-- index.css
| |-- Firebase/
| | |-- firebase.init.js
| |-- Hooks/
| | |-- useAxios.jsx
| | |-- useDocumentTitle.jsx
| | |-- useUserRole.jsx
| |-- Router/
| | |-- router.jsx
| |-- Layout/
| | |-- Home/
| | |-- Admin/
| |-- Components/
| |-- Authentication/
| |-- Donor/
| |-- Profile/
| |-- Shared/
| |-- Static/
| |-- Errors/
|
|-- Server-Side/
|-- API_DOCUMENTATION.md
|-- package.json
|-- tsconfig.json
|-- vercel.json
|-- api/
| |-- index.ts
|-- src/
|-- app.ts
|-- server.ts
|-- seed.ts
|-- config/
| |-- index.ts
| |-- db.ts
| |-- firebase.ts
|-- constants/
|-- middlewares/
|-- modules/
| |-- user/
| |-- donor/
| |-- location/
|-- utils/
|-- data/
|-- bangladesh-locations.json
Key locations:
- Frontend routing and page composition:
Client-Side/src/Router/router.jsx - Frontend API client setup:
Client-Side/src/Hooks/useAxios.jsx - Firebase initialization:
Client-Side/src/Firebase/firebase.init.js - Backend app bootstrap and middleware:
Server-Side/src/app.ts - Backend API module routes/controllers/services:
Server-Side/src/modules/*
- User registration and login with Firebase Authentication.
- Role-aware access model (
admin,donor). - Donor registration workflow with pending approval.
- Admin dashboard route for moderation.
- Donor search by blood type and geographic filters.
- Donor availability management.
- Bangladesh location hierarchy endpoints.
- Standardized API response format.
- Request validation with Zod.
- Global error handling with consistent error schema.
- Rate limiting and security middleware integration.
- Open the website home page.
- Go to Find Donors.
- Filter by blood group and location.
- View approved donor profiles.
- Register or log in using Firebase authentication.
- Complete your donor profile with blood group, phone, and location.
- Wait for admin approval.
- Update your profile and availability when needed.
- Log in with an account that has
adminrole. - Review pending donor requests.
- Approve or reject donor profiles.
- Manage user roles and donor records.
| Full Name | Role | |||
|---|---|---|---|---|
| Md. Abdullah Al Noman | Frontend Developer | |||
| Reduan Ahmad | Backend Developer | |||
| Adnan Iqbal | Frontend Developer |
- This project is a university course project.
- It was developed as a group project.
Contributions are welcome.
- Fork the repository.
- Create a feature branch from
main. - Make focused changes with clear commit messages.
- Run lint/build checks before opening a pull request.
- Open a pull request with:
- Summary of what changed
- Why it changed
- Testing notes
- Address review feedback and keep the branch up to date.
Recommended quality checks:
# Frontend
cd Client-Side
npm run lint
npm run build
# Backend
cd ../Server-Side
npm run lint
npm run buildThis project is distributed under the ISC License.
- Language is kept clear and direct.
- Heading hierarchy and formatting are consistent.
- No emoji characters are used.
- API section includes base URL, authentication, all endpoints, request and response examples, and error formats.
- User availability field for donors (toggle in profile)
- Improved admin filtering for pending donors
- Demo login credentials and seeding
- Comprehensive production deployment guide
- Bangladeshi image integration guide
- Production-ready database structure
- Fixed donor routing issue (/pending route ordering)
- Fixed admin dashboard filtering
- Improved Firebase authentication flow
If upgrading from v1.0.0:
- Stop running servers
- Delete existing MongoDB data or use backup
- Run
npm run seedto populate with v1.1.0 data structure - Update environment variables if migrating to production
- Redeploy frontend and backend
Port already in use:
# Vite (port 5173)
npm run dev -- --port 5174
# Express (port 5000)
PORT=5001 npm run devMongoDB connection error:
- Verify
MONGODB_URIin.env - Check MongoDB service is running
- For MongoDB Atlas: verify IP whitelist
Firebase auth not working:
- Verify Firebase configuration in
.envandfirebase.init.js - Enable Email/Password provider in Firebase Console
- Check CORS settings if API calls fail
Build errors:
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install