A production-ready MERN stack application that connects volunteers with organizations using a hybrid AI matching system, with GPS-verified attendance, mentorship, and digital certificate generation.
impactmatch/
βββ backend/
β βββ config/db.js # MongoDB connection
β βββ controllers/ # Route handlers (MVC)
β β βββ authController.js
β β βββ opportunityController.js
β β βββ applicationController.js
β β βββ attendanceController.js
β β βββ certificateController.js
β β βββ mentorshipController.js
β β βββ matchingController.js
β βββ middleware/
β β βββ auth.js # JWT protect + role authorize
β β βββ validate.js # express-validator rules
β βββ models/
β β βββ User.js
β β βββ Opportunity.js
β β βββ Application.js
β β βββ Mentorship.js
β β βββ Attendance.js
β β βββ Certificate.js
β βββ routes/ # Express route definitions
β βββ services/
β β βββ certificateService.js # PDF generation
β βββ utils/
β β βββ matchingAlgorithm.js # Hybrid AI matching
β β βββ haversine.js # GPS distance calculation
β β βββ generateToken.js # JWT creation
β βββ scripts/seed.js # Database seeding
β βββ Dockerfile
β βββ .env.example
β βββ server.js
β
βββ frontend/
β βββ public/index.html
β βββ src/
β β βββ components/
β β β βββ Navbar.js
β β β βββ ProtectedRoute.js
β β β βββ OpportunityCard.js
β β βββ context/AuthContext.js # Global auth state
β β βββ pages/
β β β βββ Login.js
β β β βββ Register.js
β β β βββ Dashboard.js # Role-aware router
β β β βββ VolunteerDashboard.js
β β β βββ OrganizationDashboard.js
β β β βββ MentorDashboard.js
β β β βββ Opportunities.js # AI-ranked listing
β β β βββ PostOpportunity.js
β β β βββ Applications.js # With GPS check-in
β β β βββ Mentorship.js
β β β βββ Certificates.js
β β β βββ VerifyCertificate.js # Public verification
β β βββ services/api.js # Axios with interceptors
β β βββ App.js
β βββ Dockerfile
β βββ nginx.conf
β
βββ docker-compose.yml
- Node.js 18+
- MongoDB 6+ (local or Atlas)
- npm or yarn
git clone <your-repo>
cd impactmatch
# Install backend dependencies
cd backend
npm install
# Install frontend dependencies
cd ../frontend
npm install# Backend
cd backend
cp .env.example .env
# Edit .env with your values:
# - MONGO_URI: your MongoDB connection string
# - JWT_SECRET: a long random secret (min 32 chars)
# - CLIENT_URL: http://localhost:3000
# Frontend (optional β proxy is pre-configured)
cd ../frontend
cp .env.example .envcd backend
npm run seed
# Creates: org@impactmatch.com, volunteer@impactmatch.com, mentor@impactmatch.com
# All passwords: password123# Terminal 1: Start backend
cd backend
npm run dev # nodemon with hot reload
# Terminal 2: Start frontend
cd frontend
npm start # React dev server on :3000Visit: http://localhost:3000
# Build and start all services
JWT_SECRET=your_secret_here docker-compose up --build
# Stop
docker-compose down
# Stop and remove volumes
docker-compose down -vServices:
- Frontend: http://localhost:3000 (nginx)
- Backend API: http://localhost:5000
- MongoDB: localhost:27017
| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | /api/auth/register |
Public | Register new user |
| POST | /api/auth/login |
Public | Login, returns JWT |
| GET | /api/auth/me |
Private | Get current user |
| PUT | /api/auth/profile |
Private | Update profile |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/opportunities |
Public | List all (paginated) |
| GET | /api/opportunities/my |
Organization | My listings |
| GET | /api/opportunities/:id |
Public | Single opportunity |
| POST | /api/opportunities |
Organization | Create listing |
| PUT | /api/opportunities/:id |
Organization | Update |
| DELETE | /api/opportunities/:id |
Organization | Delete |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/matching/opportunities |
Volunteer | AI-ranked opportunities |
| GET | /api/matching/score/:id |
Volunteer | Score for one opportunity |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | /api/applications |
Volunteer | Apply to opportunity |
| GET | /api/applications/my |
Volunteer | My applications |
| GET | /api/applications/opportunity/:id |
Organization | Applicants |
| PUT | /api/applications/:id/status |
Organization | Accept/Reject/Complete |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | /api/attendance/checkin |
Volunteer | GPS check-in |
| POST | /api/attendance/checkout |
Volunteer | GPS check-out |
| GET | /api/attendance/my |
Volunteer | My attendance history |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | /api/certificates/issue/:applicationId |
Organization | Issue certificate |
| GET | /api/certificates/my |
Volunteer | My certificates |
| GET | /api/certificates/verify/:code |
Public | Verify certificate |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/mentorship/mentors |
Authenticated | Available mentors |
| POST | /api/mentorship/request |
Volunteer | Request a mentor |
| GET | /api/mentorship/my |
Volunteer | My mentorships |
| GET | /api/mentorship/requests |
Mentor | Requests received |
| PUT | /api/mentorship/:id/respond |
Mentor | Accept/Reject |
| POST | /api/mentorship/:id/session |
Mentor | Add session notes |
| PUT | /api/mentorship/:id/complete |
Mentor | Approve completion |
Located in backend/utils/matchingAlgorithm.js:
Final Score = (0.4 Γ interestMatch) + (0.3 Γ skillMatch) + (0.3 Γ semanticScore)
- Interest Match: Jaccard similarity between volunteer interests and opportunity categories
- Skill Match: Jaccard similarity between volunteer skills and required skills
- Semantic Match: Cosine similarity between embedding vectors (placeholder β replace
generateEmbedding()with OpenAI embeddings or HuggingFace sentence-transformers for production)
Returns:
{
"matchScore": 0.72,
"matchPercentage": 72,
"matchedSkills": ["Python", "Teaching"],
"skillGap": ["Leadership"],
"categoryMatched": true,
"semanticScore": 0.68,
"breakdown": {
"interestMatch": 0.80,
"skillMatch": 0.67,
"semanticScore": 0.68
}
}Check-in requires the volunteer to be within CHECK_IN_RADIUS_METERS (default: 200m) of the opportunity location.
The Haversine formula is used to compute great-circle distance. Remote opportunities skip location validation.
- Volunteer applies and gets accepted
- Volunteer checks in and out via GPS
- Organization marks application as "completed"
- Organization issues certificate via
/api/certificates/issue/:applicationId - System generates a PDF with unique
verificationCode - Anyone can verify at
/verify/:code(public endpoint)
- JWT: HS256, configurable expiration, validated on every protected route
- bcrypt: Cost factor 12 for password hashing
- Role-based middleware:
authorize('volunteer', 'organization')guards - Input validation: express-validator on all mutation endpoints
- CORS: Restricted to
CLIENT_URLin production - No secrets in code: All sensitive values via environment variables
- GPS anti-fraud: Server-side radius validation (not client-trusting)
- Certificate fraud prevention: Unique IDs + org approval required
User.email(unique)Application.volunteerId + opportunityId(compound unique)Certificate.verificationCode(unique)Opportunity.category,organizationId, geolocation
- Backend is stateless (JWT) β run N replicas behind a load balancer
- Use MongoDB Atlas for managed horizontal scaling
- Add Redis for caching AI match scores (expensive computation)
// Replace generateEmbedding() in matchingAlgorithm.js:
const { OpenAI } = require('openai');
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const generateEmbedding = async (text) => {
const res = await client.embeddings.create({ model: 'text-embedding-3-small', input: text });
return res.data[0].embedding;
};- Set
NODE_ENV=production - Use a strong
JWT_SECRET(32+ random chars) - Enable MongoDB Atlas TLS
- Set
CLIENT_URLto your actual domain - Configure HTTPS (via nginx or cloud provider)
- Set up log aggregation (e.g., Winston + CloudWatch)
- Add rate limiting (express-rate-limit)
- Configure automated MongoDB backups
- Set up monitoring (PM2 or a cloud service)
curl -X POST http://localhost:5000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"email": "jane@example.com",
"password": "securepass",
"role": "volunteer",
"skills": ["Python", "Teaching"],
"interests": ["education", "technology"]
}'curl http://localhost:5000/api/matching/opportunities \
-H "Authorization: Bearer <your_token>"curl http://localhost:5000/api/certificates/verify/ABCD1234EF56- Real OpenAI/HuggingFace embeddings for semantic matching
- In-app messaging between volunteers and organizations
- Admin dashboard
- Email notifications (nodemailer/SendGrid)
- Mobile app (React Native)
- Blockchain certificate anchoring
- Impact analytics dashboard