A full-stack volunteer-need matching system for NGOs, powered by Google Gemini AI. This platform connects community needs with available volunteers using intelligent matching algorithms, NLP-powered data extraction, a Gemini-driven chatbot, and real-time notifications.
๐ Repository: https://github.com/ENTRYDOWN99/solution-challenge
git clone https://github.com/ENTRYDOWN99/solution-challenge.git
cd solution-challengeโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ React โโโโโถโ Node.js โโโโโถโ SQLite โ
โ Frontend โ โ Express API โ โ Database โ
โ (Vite) โ โ โ โโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโ
โ โโโโโถโ In-Memory โ
โ โ โ Cache โ
โ โ โโโโโโโโโโโโโโโโ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโ
โ โโโโโถโ Python NLP Service โ
โโโโโโโโโโโโโโโโ โ Flask + Gemini AI โ
โโโโโโโโโโโโโโโโโโโโโโโโ
- ๐ค Gemini AI Integration โ Enhanced NLP extraction, human-readable match explanations, and a volunteer-facing chatbot powered by
gemini-1.5-flash - ๐ง Intelligent Matching Engine โ Matches volunteers to needs using skill overlap, distance, availability, and trust score
- ๐ NLP Text Extraction โ Extract structured data from paper surveys using OCR + spaCy NLP, enriched by Gemini
- ๐ฌ Volunteer Chatbot โ Multi-turn AI assistant with persistent sessions, aware of live platform context (open needs count, user role)
- ๐ Real-time Dashboard โ Analytics, trends, heatmaps, and coverage gap analysis
- ๐จ Urgency Scoring โ Automatic urgency calculation:
severityร0.4 + peopleร0.3 + time_sensitiveร0.2 + vulnerabilityร0.1 - ๐ธ OCR Pipeline โ Upload survey images โ Tesseract OCR โ Gemini-enhanced NLP extraction โ auto-create needs
- ๐ Role-based Access โ Separate views for NGO admins, volunteers, and super admins
- ๐ Notifications โ SMS (Twilio) and email (Nodemailer) for task assignments
- ๐บ๏ธ Heatmap Visualization โ Leaflet.js map with color-coded urgency markers
- ๐ DBSCAN Clustering โ Group nearby needs (within 200m) for efficient resource allocation
- ๐ API Webhooks โ Accept external need data from partner NGO systems
/project-root
โโโ frontend/ # React 18 + Vite SPA
โ โโโ src/
โ โ โโโ components/ # Reusable UI components
โ โ โโโ pages/ # Route pages
โ โ โโโ context/ # React Context providers
โ โ โโโ services/ # API service layer
โ โโโ index.html
โโโ backend/ # Node.js + Express REST API
โ โโโ src/
โ โ โโโ config/ # DB, cache, app config
โ โ โโโ controllers/ # Route handlers
โ โ โ โโโ chatController.js # Gemini chat proxy
โ โ โโโ middleware/ # Auth, upload, error handling
โ โ โโโ routes/
โ โ โ โโโ chat.js # POST /api/chat
โ โ โโโ services/ # Email, SMS services
โ โ โโโ utils/ # Helpers (haversine, scoring)
โ โ โโโ server.js # Entry point
โ โโโ uploads/ # File upload storage
โโโ nlp-service/ # Python Flask + Gemini microservice
โ โโโ app.py # NLP + Gemini endpoints
โ โโโ requirements.txt # includes google-generativeai
โ โโโ .env # GEMINI_API_KEY (local only, not committed)
โโโ db/ # Database files
โ โโโ 001_init.sql # Schema definition
โ โโโ seed.js # Seed data script
โโโ docker-compose.yml
โโโ README.md
- Node.js 18+
- Python 3.11+ (optional โ for NLP service)
- Docker & Docker Compose (optional)
- Google Gemini API key (optional โ platform degrades gracefully without it)
# Copy and configure the root .env (add your Gemini key here)
echo "GEMINI_API_KEY=your_key_here" > .env
# Start all services
docker-compose up --build
# Seed the database (first time only)
docker exec cap_backend npm run seedServices:
- Frontend: http://localhost:3000
- Backend API: http://localhost:5000
- NLP Service: http://localhost:5001
cd backend
npm install
cp .env.example .env # Configure environment variables
npm run seed # Seed initial data (first time only)
npm run dev # Starts on port 5000cd nlp-service
pip install -r requirements.txt
python -m spacy download en_core_web_sm
# Add your Gemini API key (get one free at https://aistudio.google.com/app/apikey)
echo "GEMINI_API_KEY=your_key_here" > .env
python app.py # Starts on port 5001If the NLP service is not running, the backend automatically falls back to local regex-based extraction.
IfGEMINI_API_KEYis not set, all endpoints still work โ Gemini features are silently disabled.
cd frontend
npm install
npm run dev # Starts on port 3000| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/auth/register |
Register new user | No |
| POST | /api/auth/login |
Login, returns JWT | No |
| POST | /api/auth/refresh |
Refresh access token | No |
| GET | /api/auth/me |
Get current user | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/needs |
Create need (auto urgency scoring) | Yes |
| GET | /api/needs |
List needs (filterable, paginated) | Yes |
| GET | /api/needs/:id |
Get need with assignments | Yes |
| PUT | /api/needs/:id |
Update need | Admin |
| DELETE | /api/needs/:id |
Soft delete need | Admin |
| POST | /api/needs/bulk-upload |
OCR upload paper survey | Yes |
| GET | /api/needs/heatmap |
Heatmap data (lat/lng + urgency) | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/volunteers/profile |
Create/update profile | Yes |
| GET | /api/volunteers |
List volunteers (filterable) | Yes |
| GET | /api/volunteers/:id |
Get full profile | Yes |
| PUT | /api/volunteers/:id/availability |
Update schedule | Yes |
| GET | /api/volunteers/:id/tasks |
Task history | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/matching/run |
Trigger matching engine | Admin |
| GET | /api/matching/suggestions/:need_id |
Top 5 matches | Yes |
| POST | /api/matching/assign |
Assign volunteer | Admin |
| POST | /api/matching/accept/:task_id |
Accept task | Yes |
| POST | /api/matching/complete/:task_id |
Complete task | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/analytics/summary |
Dashboard statistics | Yes |
| GET | /api/analytics/trends |
30-day trends | Yes |
| GET | /api/analytics/coverage-gaps |
Low coverage areas | Yes |
| GET | /api/analytics/top-needs |
Top 5 urgent needs | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/orgs |
Create organization | Admin |
| GET | /api/orgs |
List organizations | Yes |
| GET | /api/orgs/:id/needs |
Org's needs | Yes |
| POST | /api/orgs/webhook |
External webhook (API key) | API Key |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/chat |
Send message to Gemini volunteer assistant | Yes |
Request body:
{ "message": "What open needs are near me?" }Response:
{ "reply": "There are currently 12 open needs on the platform..." }| Method | Endpoint | Description |
|---|---|---|
| POST | /extract |
Extract fields from text (Gemini-enhanced) |
| POST | /match-score |
Compute match score + Gemini explanation |
| POST | /cluster-needs |
DBSCAN clustering |
| POST | /chat |
Gemini chatbot (called via backend proxy) |
| GET | /health |
Health check (gemini_available field) |
| Variable | Description | Default |
|---|---|---|
JWT_SECRET |
JWT signing secret | Required |
JWT_REFRESH_SECRET |
Refresh token secret | Required |
PORT |
Server port | 5000 |
NODE_ENV |
Environment | development |
NLP_SERVICE_URL |
Python service URL | http://localhost:5001 |
FRONTEND_URL |
Frontend URL for CORS | http://localhost:3000 |
REDIS_URL |
Redis connection string (optional) | In-memory fallback used |
TWILIO_SID |
Twilio account SID | Optional |
TWILIO_AUTH_TOKEN |
Twilio auth token | Optional |
TWILIO_PHONE |
Twilio phone number | Optional |
SMTP_HOST |
SMTP server host | Optional |
SMTP_USER |
SMTP username | Optional |
SMTP_PASS |
SMTP password | Optional |
| Variable | Description | Default |
|---|---|---|
GEMINI_API_KEY |
Google Gemini API key โ get yours free | Optional |
PORT |
Flask service port | 5001 |
Graceful degradation: If
GEMINI_API_KEYis absent or the Gemini call fails, all endpoints continue to work using spaCy/regex logic. No crashes.
| Variable | Description | Default |
|---|---|---|
VITE_API_URL |
Backend API URL | http://localhost:5000/api |
Gemini reads the raw field-report text and returns a structured JSON object that overrides and enriches the base spaCy/regex result โ providing more accurate location, category, severity, and a human-readable description.
After the numeric score is computed, Gemini generates a one-sentence natural-language explanation:
{
"match_score": 0.82,
"explanation": "Raj is an 82% match โ his medical skills are exactly what's needed and he lives just 3 km away with a strong trust record.",
"distance_km": 3.1,
"breakdown": { "skill": 1.0, "distance": 0.88, "availability": 0.5, "trust": 0.75 }
}Multi-turn conversational assistant with:
- Persistent in-memory session per user
- Live platform context (open needs count, user role)
- Graceful 503 response if Gemini is unconfigured
match_score = skill_match ร 0.4 + distance_score ร 0.3 + availability ร 0.2 + trust ร 0.1
- Skill Match (40%):
1.0if volunteer has the need's category as a skill - Distance Score (30%):
max(0, 1 - distance / max_radius_km) - Availability (20%):
1.0if volunteer is available during need's time - Trust Score (10%):
trust_score / 100 - Hard Filters: Score =
0if no skill match OR distance > max radius
Needs with urgency_score > 0.85 trigger real-time matching immediately on creation.
urgency = severity_norm ร 0.4 + people_norm ร 0.3 + time_sensitive ร 0.2 + vulnerability_norm ร 0.1
| Job | Schedule | Description |
|---|---|---|
| Batch Matching | Every 15 minutes | Runs matching engine for all open needs |
| Token Cleanup | Daily at 2 AM | Removes expired refresh tokens |
MIT License โ see LICENSE for details.