Smart. Secure. Automated.
Privacy-first campus lost & found platform with intelligent heuristic matching and fraud-proof ownership verification.
🌐 Live Demo · ⚙️ API Health · 📦 Installation · 🤝 Contributing · 📡 API
- What is ReclaimX?
- ✨ Key Features
- 📸 Screenshots
- 🛠 Tech Stack
- 🏗 Project Structure
- 🔧 How the Matching Engine Works
- 🔒 Ownership Verification (Anti-Fraud)
- 🏆 Trust Score System
- 📊 Database Schema
- 📡 API Reference
- 📦 Getting Started
- 🚀 Deployment
- 🔐 Security
- 🧪 Testing & CI
- 🗺 Roadmap
- 👥 Team
- 🤝 Contributing
- 📄 License
ReclaimX replaces the traditional campus lost & found notice board with an automated, privacy-first system. Students report lost or found items, and a custom weighted scoring engine matches them in real time based on text similarity, image presence, location overlap, and time proximity.
| Goal | Description |
|---|---|
| Privacy First | Only the item name is publicly visible. Descriptions, photos, and verification details are encrypted and private |
| Fraud Prevention | Ownership verified via 3 secret questions only the real owner could answer. 3 failed attempts = account suspended |
| Trust System | Users earn Bronze → Silver → Gold status for successful returns |
| Works Offline | Full PWA with service worker caching and offline submission queue |
- Real-time Matching Engine — Custom heuristic scoring (Jaccard similarity + location + time decay)
- Privacy-First Design — Sensitive data encrypted, only item names public
- Fraud-Proof Verification — 3 secret questions with server-side answer scoring
- Trust Score System — Bronze → Silver → Gold progression with points for successful returns
- PWA Support — Installable, works offline with service worker caching
- Multi-Auth Providers — Email/Password, Google, GitHub via Firebase
- Image Upload — Cloudinary integration for item photos
- Multi-Campus Support — Island-based matching by campus_id
- Rate Limiting — 100 requests/15 min per IP to prevent abuse
- Sensitive Data Filter — Blocks Aadhaar, PAN, card numbers in descriptions
| Home Page | Login Page | Signup Page |
|---|---|---|
| 🏠 View Full Homepage | ![]() |
![]() |
| Dashboard | Browse Items |
|---|---|
![]() |
![]() |
| My Matches | Report Lost Item |
|---|---|
![]() |
![]() |
| Report Found Item | Profile |
|---|---|
![]() |
![]() |
📁 Full-resolution screenshots live in docs/screenshots/.
| Layer | Technology |
|---|---|
| Frontend | Vanilla HTML5, CSS3, JavaScript (ES Modules) |
| PWA | Service Worker + Web App Manifest |
| Auth | Firebase Auth (Email/Password, Google, GitHub) |
| Backend | Node.js + Express.js |
| Database | Supabase (PostgreSQL) |
| Image Storage | Cloudinary v2 |
| Matching Engine | Custom heuristic scoring (Jaccard similarity + location + time decay) |
| Security | Helmet.js, express-rate-limit, Firebase ID token verification |
| Frontend Hosting | Vercel |
| Backend Hosting | Render |
RECLAIMX/
├── frontend/ ← Deployed on Vercel (root dir: frontend/)
│ ├── index.html ← Public landing page
│ ├── manifest.json ← PWA manifest
│ ├── service-worker.js ← Offline caching
│ ├── vercel.json ← Clean URL rewrites + cache headers
│ ├── .env.example ← No secrets needed for frontend
│ │
│ ├── pages/
│ │ ├── login.html
│ │ ├── register.html
│ │ ├── dashboard.html ← Stats, recent activity, my reports
│ │ ├── browse.html ← Public browse with search/filter
│ │ ├── report-lost.html ← Hidden verification attributes
│ │ ├── report-found.html
│ │ ├── matches.html ← Score ring, verify claim flow
│ │ ├── profile.html ← Avatar, trust score, activity
│ │ ├── security.html ← Security protocol and details page
│ │ ├── privacy.html ← Data collection and user privacy policy
│ │ ├── terms.html ← Terms of Service and physical safety liability shield
│ │ ├── cookies.html ← Cookie policy and session tokens usage page
│ │ └── 404.html
│ │
│ ├── assets/
│ │ ├── css/global.css ← Full design system (dark theme)
│ │ ├── js/
│ │ │ ├── main.js ← API_BASE, toast, sidebar init
│ │ │ ├── auth-guard.js ← Back/forward button bypass (bfcache)
│ │ │ ├── auth.js ← Session guard, token refresh
│ │ │ ├── firebase-config.js ← Loads config from backend
│ │ │ └── pwa.js ← SW registration, offline queue
│ │ └── icons/
│ │
│ └── components/
│ ├── sidebar.html ← Injected via fetch() on every page
│ └── toast.html ← Rich toast with progress bar
│
└── backend/ ← Deployed on Render (root dir: backend/)
├── server.js ← Express entry point (port 5000)
├── package.json
├── .env ← Secrets — never commit
├── .env.example
│
├── config/
│ ├── firebase.js ← Firebase Admin SDK
│ ├── supabase.js ← Supabase service_role client
│ ├── cloudinary.js ← Cloudinary v2 + multer memoryStorage
│ └── serviceAccountKey.json ← Firebase key — never commit
│
├── middleware/
│ ├── authMiddleware.js ← Firebase token verification
│ └── errorHandler.js ← Global error + 404 handler
│
├── routes/
│ ├── authRoutes.js ← /api/auth/*
│ ├── itemRoutes.js ← /api/items/*
│ ├── matchRoutes.js ← /api/matches/*
│ └── configRoutes.js ← /api/config/firebase
│
├── ai/
│ └── matchingEngine.js ← Heuristic scoring engine
│
└── utils/
├── verificationEngine.js ← Ownership answer scoring
├── sensitiveDataFilter.js ← Blocks Aadhaar, PAN, card numbers
└── emailService.js ← Resend email notifications (planned)
| Component | Port | Entry Point | Hosting |
|---|---|---|---|
| Frontend | 3000 (local) | frontend/index.html |
Vercel |
| Backend | 5000 (local) | backend/server.js |
Render |
| API Root | http://localhost:5000/api |
— | — |
When a lost or found item is submitted, the engine queries all open opposing items on the same campus with the same category, then scores each pair:
[ \text{Final Score} = (\text{Text} \times 40%) + (\text{Image} \times 30%) + (\text{Location} \times 20%) + (\text{Time} \times 10%) ]
| Signal | Method |
|---|---|
| Text | Jaccard similarity on item name (70%) + description (30%) |
| Image | Presence score — 65 if both have images, 40 if one, 20 if neither |
| Location | Token overlap between last-seen and found locations |
| Time decay | Linear decay over 72 hours — older reports score lower |
A claim is created only if score ≥ 40 and campus + category both match exactly.
⚠️ Note: Image signal is a presence placeholder. Vector embedding similarity (MobileNet + pgvector) is planned for v2.
After a match is created, the claimer answers 3 questions drawn from private hidden attributes:
- Interior colour / lining
- Unique marks, scratches, stickers, or engravings
- What the item contains
Answers checked server-side using Jaccard word similarity:
- Score ≥ 60% → verified
- Below 60% → strike logged
- 3 strikes → account suspended
| Level | Points | Notes |
|---|---|---|
| 🥉 Bronze Helper | 0–49 pts | Default on signup |
| 🥈 Silver Helper | 50–99 pts | Trusted member |
| 🥇 Gold Hero | 100+ pts | Campus hero |
+10 points awarded to both parties on each successful item return.
Run this SQL in your Supabase SQL Editor:
CREATE TABLE users (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
firebase_uid TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
campus_id TEXT DEFAULT 'campus_a',
photo TEXT DEFAULT '',
trust_score INTEGER DEFAULT 0,
trust_level TEXT DEFAULT 'Bronze',
failed_claims INTEGER DEFAULT 0,
is_suspended BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE lost_items (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES users(id),
campus_id TEXT NOT NULL,
item_name TEXT NOT NULL, -- PUBLIC
description TEXT, -- PRIVATE
category TEXT,
last_seen_location TEXT, -- PUBLIC
image_urls TEXT[] DEFAULT '{}', -- PRIVATE
hidden_color_inside TEXT, -- PRIVATE (verification)
hidden_unique_marks TEXT, -- PRIVATE (verification)
hidden_contains TEXT, -- PRIVATE (verification)
status TEXT DEFAULT 'Lost', -- Lost \[|\] Pending \[|\] Resolved
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE found_items (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES users(id),
campus_id TEXT NOT NULL,
item_name TEXT NOT NULL, -- PUBLIC
description TEXT, -- PRIVATE
category TEXT,
found_location TEXT, -- PUBLIC
image_url TEXT DEFAULT '', -- PRIVATE
status TEXT DEFAULT 'Found', -- Found \[|\] Resolved
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE claims (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
lost_item_id UUID REFERENCES lost_items(id),
found_item_id UUID REFERENCES found_items(id),
claimant_id UUID REFERENCES users(id),
match_score FLOAT DEFAULT 0,
answer_1 TEXT, answer_2 TEXT, answer_3 TEXT,
verification_score FLOAT DEFAULT 0,
handover_otp VARCHAR(6),
loster_confirmed BOOLEAN DEFAULT false,
founder_confirmed BOOLEAN DEFAULT false,
status TEXT DEFAULT 'Pending', -- Pending \[|\] Verified \[|\] Rejected \[|\] Resolved
created_at TIMESTAMPTZ DEFAULT NOW()
);
⚠️ Use the service_role key in your backend.env, not the anon key. The anon key will be blocked by Row Level Security.
Base URL: https://reclaimx.onrender.com/api (production) or http://localhost:5000/api (local)
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /session |
— | Verify Firebase token + upsert user |
| GET | /me |
✅ | Get current user profile |
| PUT | /profile |
✅ | Update display name / clear photo |
| POST | /avatar |
✅ | Upload profile photo to Cloudinary |
| POST | /forgot-password |
— | Send Firebase password reset email |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
— | Browse open lost & found items |
| GET | /me |
✅ | Get current user's reports |
| POST | /lost |
✅ | Report a lost item (triggers matching) |
| POST | /found |
✅ | Report a found item (triggers matching) |
| DELETE | /lost/:id |
✅ | Delete own lost report |
| DELETE | /found/:id |
✅ | Delete own found report |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
✅ | Get all claims for current user |
| POST | /verify |
✅ | Submit ownership verification answers |
| POST | /confirm-handover/:id |
✅ | Confirm physical handover |
| POST | /resolve/:id |
✅ | Verify OTP and resolve claim |
| POST | /dismiss/:id |
✅ | Dismiss a match |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/config/firebase |
— | Firebase client config (safe to expose) |
| GET | /api/health |
— | Server health check |
curl -X POST https://reclaimx.onrender.com/api/auth/session \
-H "Content-Type: application/json" \
-d '{
"firebaseToken": "YOUR_FIREBASE_ID_TOKEN_HERE"
}'Response:
{
"success": true,
"user": {
"id": "uuid-here",
"firebase_uid": "firebase-uid",
"name": "John Doe",
"email": "john@example.com",
"campus_id": "campus_a",
"trust_score": 0,
"trust_level": "Bronze"
}
}curl -X GET https://reclaimx.onrender.com/api/auth/me \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE"Response:
{
"success": true,
"user": {
"id": "uuid-here",
"firebase_uid": "firebase-uid",
"name": "John Doe",
"email": "john@example.com",
"campus_id": "campus_a",
"photo": "",
"trust_score": 10,
"trust_level": "Bronze",
"failed_claims": 0,
"is_suspended": false
}
}curl -X POST https://reclaimx.onrender.com/api/items/lost \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE" \
-d '{
"campus_id": "campus_a",
"item_name": "iPhone 13 Pro",
"description": "Midnight green, 128GB, has a crack on the back",
"category": "Electronics",
"last_seen_location": "Library Floor 2",
"hidden_color_inside": "Black leather lining",
"hidden_unique_marks": "Crack on back near camera, Apple sticker on case",
"hidden_contains": "AirPods Pro case, USB-C cable, phone manual"
}'Response:
{
"success": true,
"message": "Lost item reported successfully",
"item": {
"id": "uuid-here",
"user_id": "uuid-here",
"campus_id": "campus_a",
"item_name": "iPhone 13 Pro",
"category": "Electronics",
"last_seen_location": "Library Floor 2",
"status": "Lost",
"created_at": "2026-06-04T11:00:00.000Z"
},
"matches_found": 1,
"matches": [
{
"claim_id": "claim-uuid",
"found_item_id": "found-uuid",
"match_score": 67.5,
"founder_name": "Jane Smith"
}
]
}curl -X POST https://reclaimx.onrender.com/api/items/found \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE" \
-d '{
"campus_id": "campus_a",
"item_name": "iPhone 13 Pro",
"description": "Found near library, midnight green color",
"category": "Electronics",
"found_location": "Library Floor 2"
}'Response:
{
"success": true,
"message": "Found item reported successfully",
"item": {
"id": "uuid-here",
"user_id": "uuid-here",
"campus_id": "campus_a",
"item_name": "iPhone 13 Pro",
"category": "Electronics",
"found_location": "Library Floor 2",
"status": "Found",
"created_at": "2026-06-04T11:00:00.000Z"
},
"matches_found": 1,
"matches": [
{
"claim_id": "claim-uuid",
"lost_item_id": "lost-uuid",
"match_score": 67.5,
"loster_name": "John Doe"
}
]
}curl -X GET "https://reclaimx.onrender.com/api/items?campus_id=campus_a&category=Electronics"Response:
{
"success": true,
"items": [
{
"id": "uuid-1",
"item_name": "iPhone 13 Pro",
"category": "Electronics",
"last_seen_location": "Library Floor 2",
"status": "Lost",
"created_at": "2026-06-04T10:00:00.000Z",
"has_image": true
},
{
"id": "uuid-2",
"item_name": "iPhone 13 Pro",
"category": "Electronics",
"found_location": "Library Floor 2",
"status": "Found",
"created_at": "2026-06-04T11:00:00.000Z",
"has_image": false
}
],
"total": 2
}curl -X POST https://reclaimx.onrender.com/api/matches/verify \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE" \
-d '{
"claim_id": "claim-uuid-here",
"answer_1": "Black leather lining",
"answer_2": "Crack on back near camera, Apple sticker",
"answer_3": "AirPods Pro case and USB-C cable"
}'Response (Verified):
{
"success": true,
"message": "Ownership verified successfully",
"claim": {
"id": "claim-uuid",
"verification_score": 78.5,
"status": "Verified"
},
"trust_score_updated": {
"previous": 10,
"current": 20
}
}Response (Not Verified):
{
"success": false,
"message": "Verification failed — answers do not match",
"claim": {
"id": "claim-uuid",
"verification_score": 45.2,
"status": "Pending",
"failed_attempts": 1,
"remaining_attempts": 2
}
}curl -X POST https://reclaimx.onrender.com/api/matches/confirm-handover/claim-uuid-here \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE"Response:
{
"success": true,
"message": "Handover confirmed — both parties rewarded",
"claim": {
"id": "claim-uuid",
"status": "Resolved",
"loster_confirmed": true,
"founder_confirmed": true
},
"trust_score_updates": {
"loster": {
"previous": 10,
"current": 20
},
"founder": {
"previous": 15,
"current": 25
}
}
}curl -X POST https://reclaimx.onrender.com/api/matches/resolve/claim-uuid-here \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"otp": "123456"
}'Response:
{
"success": true
}curl -X POST https://reclaimx.onrender.com/api/matches/dismiss/claim-uuid-here \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"reason": "Not my item"
}'Response:
{
"success": true,
"message": "Match dismissed successfully",
"claim": {
"id": "claim-uuid",
"status": "Rejected"
}
}curl -X GET https://reclaimx.onrender.com/api/matches \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE"Response:
{
"success": true,
"claims": [
{
"id": "claim-uuid",
"lost_item_id": "lost-uuid",
"found_item_id": "found-uuid",
"match_score": 67.5,
"verification_score": 78.5,
"status": "Pending",
"item_name": "iPhone 13 Pro",
"category": "Electronics",
"created_at": "2026-06-04T11:00:00.000Z"
}
],
"total": 1
}curl -X PUT https://reclaimx.onrender.com/api/auth/profile \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN_HERE" \
-d '{
"name": "John Doe Updated"
}'Response:
{
"success": true,
"message": "Profile updated successfully",
"user": {
"id": "uuid-here",
"name": "John Doe Updated",
"email": "john@example.com"
}
}curl -X GET https://reclaimx.onrender.com/api/healthResponse:
{
"status": "ok",
"timestamp": "2026-06-04T11:30:00.000Z",
"uptime": 86400,
"database": "connected",
"firebase": "connected",
"cloudinary": "connected"
}curl -X GET https://reclaimx.onrender.com/api/config/firebaseResponse:
{
"success": true,
"firebaseConfig": {
"apiKey": "AIza...",
"authDomain": "reclaimx.firebaseapp.com",
"projectId": "reclaimx",
"storageBucket": "reclaimx.appspot.com",
"messagingSenderId": "123456789",
"appId": "1:123456789:web:abc123"
}
}- Node.js ≥ 18
- npm or yarn
- Firebase project (Email/Password + Google + GitHub auth enabled)
- Supabase project
- Cloudinary account
git clone https://github.com/SniperRavan/RECLAIMX.git
cd RECLAIMXcd backend
npm install
cp .env.example .envEdit backend/.env and fill in these values:
# Server
PORT=5000
NODE_ENV=development
# Firebase Admin SDK
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_CLIENT_EMAIL=your-service-account-email@your-project.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
# Supabase
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Cloudinary
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret
# CORS (optional)
CORS_ORIGIN=http://localhost:3000
⚠️ Never commit.envorserviceAccountKey.json— they're in.gitignore.
- Go to Firebase Console → Project Settings → Service Accounts
- Click Generate New Private Key
- Save as
backend/config/serviceAccountKey.json
- Open your Supabase project's SQL Editor
- Paste the full Database Schema SQL from above
- Click Run
Terminal 1 — Backend (port 5000):
cd backend
npm run devTerminal 2 — Frontend (port 3000):
cd frontend
npx serve . -l 3000Open http://localhost:3000 in your browser.
- Go to Vercel
- Import your repo
- Settings:
- Framework Preset: Other
- Root Directory:
frontend - Build Command: (leave empty)
- Output Directory:
.
- No environment variables needed for frontend
- Deploy
- Go to Render
- New Web Service
- Settings:
- Root Directory:
backend - Start Command:
node server.js - Environment:
PORT=5000 NODE_ENV=production FIREBASE_PROJECT_ID=your-project-id FIREBASE_CLIENT_EMAIL=your-service-account-email@your-project.iam.gserviceaccount.com FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n" SUPABASE_URL=https://your-project.supabase.co SUPABASE_SERVICE_ROLE_KEY=your-service-role-key CLOUDINARY_CLOUD_NAME=your-cloud-name CLOUDINARY_API_KEY=your-api-key CLOUDINARY_API_SECRET=your-api-secret CORS_ORIGIN=https://reclaimx-chi.vercel.app
- Root Directory:
- Deploy
| Measure | Description |
|---|---|
| Secrets Management | All secrets in backend/.env — never in frontend HTML |
| Firebase Config | Served from backend endpoint — safe public config, not admin keys |
| Sensitive Data Filter | Blocks Aadhaar, PAN, card numbers in descriptions |
| Security Headers | Helmet.js sets strict headers on all responses |
| Rate Limiting | 100 requests / 15 min per IP (trust proxy enabled for Render) |
| Token Verification | Firebase ID token verified server-side on every protected route |
| Database Access | Supabase service role key is backend-only only |
| File Ignored | .env, serviceAccountKey.json in .gitignore |
- Rotate Firebase private key every 90 days
- Rotate Supabase service role key if compromised
- Use Render/Vercel secret management (not plain
.envin prod) - Enable secret scanning in GitHub repo settings
We have implemented End-to-End (E2E) testing for the critical auth and login pages.
- E2E Runner: Playwright
- Local Server Routing: Configured via
frontend/serve.jsonto handle Vercel-likecleanUrlsand routing rewrites during local testing. - Offline Fallback: If the live backend is cold-starting or offline, the frontend automatically falls back to a mock Firebase configuration on
localhost, preventing page crashes and ensuring reliable test runs.
- Go to the frontend directory:
cd frontend - Install Playwright and its browser binaries:
npm install npx playwright install --with-deps
- Run tests (either all projects or chromium only):
npx playwright test # Or run Chromium only npx playwright test --project=chromium
The repository is configured with a GitHub Actions workflow (.github/workflows/playwright.yml) that automatically runs the Playwright test suite on every push or pull request to the main or master branches.
| Priority | Feature | Status | Target |
|---|---|---|---|
| 🔴 High | Image similarity via vector embeddings (MobileNet + pgvector) | ❌ Todo | v2.0 |
| 🔴 High | Full Supabase RLS policies | ❌ Todo | v1.1 |
| 🟡 Medium | Email notifications on match creation (Resend integration) | ❌ Todo | v1.2 |
| 🟡 Medium | Verification modal UI in matches.html |
❌ Todo | v1.1 |
| 🟡 Medium | Admin dashboard for campus coordinators | ❌ Todo | v2.0 |
| 🟢 Low | Mobile app (React Native / Flutter) | ❌ Todo | v3.0 |
| 🟢 Low | Accessibility improvements (WCAG 2.1 AA) | ❌ Todo | v1.2 |
| 🟢 Low | Multi-language support (English + Hindi) | ❌ Todo | v2.0 |
| Role | Name | GitHub |
|---|---|---|
| Lead Developer | Sniper Ravan | @SniperRavan |
| Team Member | Member 2 | Add GitHub |
| Team Member | Member 3 | Add GitHub |
- Institution: Private Institute
- Project Type: Final Year Project
- Supervisor: [Add Supervisor Name]
We welcome contributions! This section explains how to get started, our workflow, and expectations.
-
Fork the repository
- Click Fork at the top-right of the repo page
- You'll get
https://github.com/YOUR_USERNAME/RECLAIMX.git
-
Clone your fork
git clone https://github.com/YOUR_USERNAME/RECLAIMX.git cd RECLAIMX -
Add upstream remote
git remote add upstream https://github.com/SniperRavan/RECLAIMX.git
-
Create a feature branch
git checkout -b feature/your-feature-name
Branch naming convention:
feature/add-dark-mode-togglefix/resolve-login-bugdocs/update-api-referencetest/add-backend-tests
-
Make your changes
- Follow existing code style
- Add comments for complex logic
- Update documentation if needed
-
Test your changes
cd backend npm run lint # TODO: npm test (once tests are added)
-
Commit your changes
git add . git commit -m "feat: add dark mode toggle button"
Commit message convention (Conventional Commits):
feat:— New featurefix:— Bug fixdocs:— Documentation changesstyle:— Code style (formatting, semicolons)refactor:— Code refactoring (no feature change)test:— Adding testschore:— Maintenance (deps, build tools)
-
Sync with upstream (before pushing)
git fetch upstream git rebase upstream/main
-
Push to your fork
git push origin feature/your-feature-name
-
Open a Pull Request
- Go to your fork on GitHub
- Click Compare & pull request
- Select base repository:
SniperRavan/RECLAIMX - Select base branch:
main - Fill in the PR template below
Copy this into your PR description:
## Description
<!-- Briefly describe what this PR does -->
## Related Issue
<!-- Link to issue number if applicable -->
Closes #123
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing Done
<!-- Describe how you tested this -->
- [ ] Local testing completed
- [ ] Screenshots attached (if UI change)
- [ ] New tests added (if applicable)
## Checklist
- [ ] My code follows the project's style guidelines
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix/feature works
- [ ] All new and existing tests passed- Frontend: Vanilla JS, ES Modules, no frameworks
- Backend: Express.js, async/await, error handling
- Naming:
- Variables:
camelCase - Constants:
UPPER_SNAKE_CASE - Files:
kebab-case.html,kebab-case.js
- Variables:
- Comments: JSDoc for functions, inline comments for complex logic
- Indentation: 2 spaces (HTML, CSS, JS)
- Quotes: Single quotes
'for JS, double quotes"for JSON
- Be respectful and inclusive
- Provide constructive feedback
- Accept constructive criticism
- Focus on what's best for the community
- Open an issue for bugs or questions
- Tag issues with appropriate labels (
bug,enhancement,question) - Join discussions in GitHub Discussions tab
- Maintainer reviews your PR within 3–5 business days
- Feedback may be given — address comments and push updates
- Once approved, PR is merged into
main - Your contribution is credited in
CONTRIBUTORS.md
MIT License — see LICENSE for full text.
Brief summary: You're free to use, modify, and distribute this project for any purpose, including commercial use, as long as you include the original copyright notice and license text.
- Firebase for authentication
- Supabase for database
- Cloudinary for image storage
- Vercel & Render for hosting
- MIT License for open-source freedom
Built with ❤️ by Sniper Ravan and team
GitHub ·
Live Demo ·
Contribute







