A modern, production-ready civic issue reporting platform that connects citizens with local authorities to report and resolve community issues efficiently.
- Overview
- Features
- Tech Stack
- Project Architecture
- Getting Started
- Environment Variables
- API Documentation
- Authentication System
- Database Schema
- Deployment
- Contributing
- License
NagarSathi (meaning "City Companion" in Hindi) is a comprehensive civic engagement platform that empowers citizens to report local infrastructure issues such as potholes, garbage accumulation, water leaks, streetlight failures, and more. The platform provides an interactive, social-media-style interface where users can:
- Report issues with photos and GPS location
- View all issues on an interactive map
- Engage with community through upvotes and comments
- Track resolution progress in real-time
- Analyze civic trends through an admin dashboard
- Rich Media Support: Upload multiple images with automatic compression and optimization
- GPS Location: Automatic location detection or manual pin placement on map
- Category Selection: Choose from 10+ predefined issue categories (Roads, Water, Electricity, Garbage, etc.)
- Detailed Descriptions: Add comprehensive issue descriptions with markdown support
- Leaflet Integration: Fully interactive map powered by OpenStreetMap
- Color-coded Markers: Visual status indicators (Red: Reported, Amber: In Progress, Green: Resolved)
- Real-time Updates: Live marker updates as statuses change
- Cluster Support: Automatic marker clustering for better performance
- Filter by Status: Toggle visibility of different issue statuses
- Upvote System: Vote on important issues to increase visibility
- Comments & Discussion: Engage in threaded discussions about issues
- Real-time Notifications: Get notified when issues are updated (via toast notifications)
- Share Functionality: Share issues on WhatsApp, Facebook, and Twitter
- Custom Profile Management: Update name, profile picture, and personal information
- Activity History: View all your reported issues and comments
- Account Settings:
- Manage connected accounts (Google OAuth)
- Active session management with remote sign-out
- Password management with secure verification
- Passkey (biometric) authentication support
- Two-factor authentication (coming soon)
- Account deletion with confirmation
- View your contribution statistics
- Track resolution rate of your reports
- See community impact metrics
- Comprehensive Table View: Sortable, filterable table of all issues
- Bulk Actions: Update multiple issues simultaneously
- Priority Assignment: Mark critical issues for faster resolution
- Advanced Filters: Filter by status, category, date range, location, upvotes
- Status Updates: Change issue status (Reported β In Progress β Resolved)
- Resolution Notes: Add detailed notes about resolution process
- Before/After Photos: Upload proof of resolution with image comparison
- Timeline Tracking: Complete audit trail of all status changes
- Issue Trends: Visualize issue frequency over time using Recharts
- Category Breakdown: Pie charts showing distribution by category
- Resolution Rate: Track average resolution time and efficiency
- Heatmap Analytics: Identify problem hotspots in the city
- Export Reports: Download analytics data as CSV/PDF
- React 18.2.0 - Modern UI library with hooks and concurrent features
- Vite 5.0.8 - Lightning-fast development server and build tool
- React Router DOM 6.21.1 - Client-side routing with nested routes
- Tailwind CSS 3.3.6 - Utility-first CSS framework
- Custom dark theme configuration
- Extended color palette with civic-themed colors
- Custom animations (dropdown, fade, slide)
- Responsive design utilities
- Lucide React 0.294.0 - Beautiful, customizable icon library (500+ icons)
- Custom CSS - Additional styling for Clerk components and animations
- TanStack React Query 5.90.12 - Powerful async state management
- Automatic caching and background refetching
- Optimistic updates
- Infinite scroll pagination
- Request deduplication
- React Context API - Global state for theme and user preferences
- @clerk/clerk-react 5.0.0 - Complete authentication solution
- OAuth providers (Google, GitHub)
- Session management with JWT
- User metadata sync via webhooks
- Custom profile UI
- Reverification for sensitive actions
- Passkey (WebAuthn) support
- Leaflet 1.9.4 - Interactive map library
- React Leaflet 4.2.1 - React wrapper for Leaflet
- Custom marker icons
- Popup components
- Geolocation API integration
- Map bounds and viewport control
- React Dropzone 14.2.3 - Drag-and-drop file upload
- Image validation
- File type restrictions
- Size limits
- Preview generation
- Axios 1.6.2 - Promise-based HTTP client
- Request/response interceptors
- Automatic Clerk token attachment
- Error handling middleware
- Request cancellation
- React Hot Toast 2.4.1 - Elegant toast notifications
- Custom styling
- Loading states
- Success/error variants
- Auto-dismiss timers
- Recharts 3.6.0 - Composable charting library
- Line charts for trends
- Pie charts for distribution
- Bar charts for comparisons
- Responsive charts
- Node.js 18+ - JavaScript runtime
- Express.js 4.18.2 - Minimal web framework
- RESTful API design
- Middleware architecture
- Error handling
- CORS configuration
- MongoDB - NoSQL document database
- Cloud-hosted on MongoDB Atlas
- Geospatial indexing for location queries
- Text indexing for search
- Aggregation pipelines
- Mongoose 8.0.3 - ODM (Object Data Modeling)
- Schema validation
- Pre/post hooks
- Virtual properties
- Population (joins)
- Custom validators
- @clerk/express 1.0.0 - Clerk Express SDK
- JWT verification middleware
- User session validation
- Webhook signature verification
- @clerk/backend 2.27.1 - Clerk Backend SDK
- User management API
- Metadata operations
- Session management
- Svix 1.15.0 - Webhook verification library
- Signature validation
- Timestamp verification
- Replay attack prevention
- Cloudinary 1.41.0 - Cloud-based media management
- Image upload and storage
- Automatic optimization
- Responsive image delivery
- Transformation API (resize, crop, format)
- CDN distribution
- Multer 1.4.5-lts.1 - Multipart form-data handler
- File upload middleware
- Memory storage buffer
- File size validation
- Multer Storage Cloudinary 4.0.0 - Cloudinary storage engine
- Direct upload to Cloudinary
- Custom file naming
- Folder organization
- CORS 2.8.5 - Cross-origin resource sharing
- Configurable origin whitelist
- Credentials support
- Preflight handling
- Dotenv 16.3.1 - Environment variable management
.envfile support- Development/production configs
- @vitejs/plugin-react 4.2.1 - React Fast Refresh support
- ESLint 8.55.0 - JavaScript linter
- React plugin
- React Hooks plugin
- Custom rules configuration
- PostCSS 8.4.32 - CSS transformations
- Autoprefixer 10.4.16 - Vendor prefix automation
- TypeScript Types - Type definitions for React and React DOM
- Nodemon 3.0.2 - Auto-restart development server
- File watching
- Configurable ignore patterns
- ES module support
nagarsathi/
β
βββ client/ # Frontend React Application
β βββ public/ # Static assets
β β βββ favicon.ico
β β
β βββ src/
β β βββ components/ # Reusable UI Components
β β β βββ common/ # Shared components
β β β β βββ Navbar.jsx # Navigation bar with custom user menu
β β β β βββ CustomUserMenu.jsx # Clerk user dropdown replacement
β β β β βββ Footer.jsx # Footer component
β β β β βββ ProtectedRoute.jsx # Route protection wrapper
β β β β βββ PageNotFound.jsx # 404 component
β β β β
β β β βββ issues/ # Issue-related components
β β β β βββ IssueCard.jsx # Issue display card
β β β β βββ IssueForm.jsx # Issue creation/edit form
β β β β βββ IssueList.jsx # List view of issues
β β β β βββ IssueFilters.jsx # Filter controls
β β β β βββ MapView.jsx # Leaflet map component
β β β β βββ CommentSection.jsx # Comments UI
β β β β βββ ShareModal.jsx # Social sharing dialog
β β β β
β β β βββ admin/ # Admin-only components
β β β β βββ AdminDashboard.jsx # Overview dashboard
β β β β βββ IssueTable.jsx # Data table with sorting
β β β β βββ AnalyticsCharts.jsx # Recharts visualizations
β β β β βββ StatusUpdateModal.jsx # Status change dialog
β β β β
β β β βββ layout/ # Layout components
β β β βββ PageLayout.jsx # Common page wrapper
β β β βββ Loader.jsx # Loading spinner
β β β
β β βββ pages/ # Page Components
β β β βββ Home.jsx # Landing/feed page
β β β βββ ReportIssue.jsx # Issue creation page
β β β βββ IssueDetail.jsx # Single issue view
β β β βββ Profile.jsx # User profile page
β β β βββ AccountSettings.jsx # Account settings page
β β β βββ AdminPanel.jsx # Admin dashboard
β β β βββ SignInPage.jsx # Clerk sign-in page
β β β βββ SignUpPage.jsx # Clerk sign-up page
β β β
β β βββ hooks/ # Custom React Hooks
β β β βββ useAuth.js # Clerk authentication hook
β β β βββ useIssues.js # React Query issues hook
β β β βββ useGeolocation.js # Browser geolocation hook
β β β βββ useDebounce.js # Debounce utility hook
β β β
β β βββ services/ # API Service Layer
β β β βββ api.js # Axios instance & API methods
β β β
β β βββ context/ # React Context Providers
β β β βββ ThemeContext.jsx # Theme state management
β β β βββ AuthContext.jsx # Auth state wrapper
β β β
β β βββ utils/ # Utility Functions
β β β βββ formatDate.js # Date formatting helpers
β β β βββ constants.js # App-wide constants
β β β
β β βββ lib/ # External library configs
β β β βββ clerk.js # Clerk configuration
β β β
β β βββ App.jsx # Main app component with routes
β β βββ main.jsx # React entry point
β β βββ index.css # Global styles & Tailwind
β β
β βββ .env # Environment variables (git-ignored)
β βββ vite.config.js # Vite configuration
β βββ tailwind.config.js # Tailwind configuration
β βββ postcss.config.js # PostCSS configuration
β βββ eslint.config.js # ESLint rules
β βββ package.json # Frontend dependencies
β
βββ server/ # Backend Express Application
β βββ config/ # Configuration Files
β β βββ db.js # MongoDB connection
β β βββ cloudinary.js # Cloudinary setup
β β
β βββ models/ # Mongoose Models
β β βββ Issue.js # Issue schema
β β βββ User.js # User schema (Clerk sync)
β β βββ Comment.js # Comment schema
β β βββ Upvote.js # Upvote schema
β β βββ Admin.js # Admin user schema
β β
β βββ controllers/ # Route Controllers
β β βββ issueController.js # Issue CRUD operations
β β βββ commentController.js # Comment operations
β β βββ upvoteController.js # Upvote logic
β β βββ adminController.js # Admin-specific operations
β β βββ analyticsController.js # Analytics & statistics
β β βββ userController.js # User profile operations
β β βββ webhookController.js # Clerk webhook handlers
β β
β βββ routes/ # Express Routes
β β βββ issues.js # Issue endpoints
β β βββ comments.js # Comment endpoints
β β βββ upvotes.js # Upvote endpoints
β β βββ admin.js # Admin endpoints
β β βββ analytics.js # Analytics endpoints
β β βββ users.js # User endpoints
β β βββ webhooks.js # Webhook endpoints
β β βββ index.js # Route aggregator
β β
β βββ middleware/ # Express Middleware
β β βββ auth.js # Clerk JWT verification
β β βββ adminCheck.js # Admin role verification
β β βββ errorHandler.js # Global error handler
β β
β βββ utils/ # Utility Functions
β β βββ logger.js # Custom logging utility
β β
β βββ .env # Environment variables (git-ignored)
β βββ server.js # Express app entry point
β βββ package.json # Backend dependencies
β
βββ docs/ # Documentation
β βββ API_DOCS.md # API endpoint documentation
β βββ DEPLOYMENT.md # Deployment guide
β
βββ .gitignore # Git ignore rules
βββ README.md # This file
βββ LICENSE # MIT License
Before you begin, ensure you have the following installed:
- Node.js >= 18.0.0 (Download)
- npm >= 9.0.0 (comes with Node.js)
- MongoDB account (MongoDB Atlas)
- Clerk account (Get Started)
- Cloudinary account (Sign Up)
- Git (Download)
git clone https://github.com/yourusername/nagarsathi.git
cd nagarsathi# Navigate to server directory
cd server
# Install dependencies
npm install
# Create environment file
cp .env.example .env
# Edit .env and add your credentials (see Environment Variables section)
# Start development server
npm run devThe backend server will start on http://localhost:5000
# Navigate to client directory (open new terminal)
cd client
# Install dependencies
npm install
# Create environment file
cp .env.example .env
# Edit .env and add your credentials
# Start development server
npm run devThe frontend will start on http://localhost:5173
- Create a MongoDB Atlas cluster (free tier available)
- Create a database user with read/write permissions
- Whitelist your IP address
- Copy the connection string to
MONGODB_URIin server.env
- Create a new Clerk application
- Enable Google OAuth provider (optional)
- Enable Passkeys in the authentication settings
- Copy publishable and secret keys to respective
.envfiles - Set up webhook endpoint:
https://your-backend-url/api/webhooks/clerk - Configure webhook events:
user.created,user.updated,user.deleted
- Sign up for Cloudinary
- Navigate to Dashboard
- Copy Cloud Name, API Key, and API Secret to server
.env - Create an upload preset (optional)
# Server Configuration
PORT=5000
NODE_ENV=development
# Database
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/nagarsathi?retryWrites=true&w=majority
# Clerk Authentication
CLERK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxx
CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxx
CLERK_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxx
# Cloudinary Configuration
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=123456789012345
CLOUDINARY_API_SECRET=xxxxxxxxxxxxxxxxxxxxx
# Client URL (for CORS)
CLIENT_URL=http://localhost:5173
# Admin Configuration (optional)
ADMIN_EMAIL=admin@example.com# API Configuration
VITE_API_URL=http://localhost:5000/api
# Clerk Authentication
VITE_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxx
# Map Configuration (optional)
VITE_MAP_DEFAULT_CENTER_LAT=28.6139
VITE_MAP_DEFAULT_CENTER_LNG=77.2090
VITE_MAP_DEFAULT_ZOOM=12http://localhost:5000/api
All protected routes require a valid Clerk JWT token in the Authorization header:
Authorization: Bearer <clerk_jwt_token>
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/issues |
Public | Get all issues with optional filters |
GET |
/issues/:id |
Public | Get single issue details |
POST |
/issues |
Required | Create new issue |
PUT |
/issues/:id |
Required (Owner) | Update issue |
DELETE |
/issues/:id |
Required (Owner) | Delete issue |
POST |
/issues/:id/upvote |
Required | Toggle upvote on issue |
GET |
/issues/:id/comments |
Public | Get comments for issue |
POST |
/issues/:id/comments |
Required | Add comment to issue |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/admin/issues |
Admin | Get all issues (admin view) |
PUT |
/admin/issues/:id/status |
Admin | Update issue status |
PUT |
/admin/issues/:id/priority |
Admin | Set issue priority |
GET |
/admin/analytics |
Admin | Get comprehensive analytics |
GET |
/admin/users |
Admin | Get user statistics |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/users/profile |
Required | Get current user profile |
PUT |
/users/profile |
Required | Update user profile |
GET |
/users/:id/issues |
Public | Get user's issues |
GET |
/users/:id/activity |
Public | Get user activity |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/webhooks/clerk |
Webhook Secret | Clerk user sync webhook |
GET /api/issues?status=reported&category=roads&limit=10&page=1Response:
{
"success": true,
"data": {
"issues": [...],
"pagination": {
"total": 45,
"page": 1,
"pages": 5,
"limit": 10
}
}
}POST /api/issues
Content-Type: multipart/form-data
Authorization: Bearer <token>
{
"title": "Pothole on Main Street",
"description": "Large pothole causing traffic issues",
"category": "roads",
"location": {
"type": "Point",
"coordinates": [77.2090, 28.6139]
},
"address": "Main Street, Sector 15",
"images": [<file1>, <file2>]
}For complete API documentation, see API_DOCS.md
NagarSathi uses Clerk for a complete authentication solution with the following features:
- Email & Password: Traditional authentication with secure password hashing
- Google OAuth: One-click sign-in with Google accounts
- Passkeys (WebAuthn): Biometric authentication support (Face ID, Touch ID, Windows Hello)
- Magic Links: Passwordless email authentication (optional)
- JWT Tokens: Secure, stateless authentication
- Session Persistence: Automatic token refresh
- Multi-device Sessions: Track and manage sessions across devices
- Remote Sign-out: End sessions from other devices
-
Re-verification: Sensitive actions require password re-entry
- Password changes
- Passkey creation
- Account deletion
-
Session Policies:
- Auto-logout after 30 days of inactivity
- Force re-authentication for high-risk actions
- Session revocation on password change
-
Webhook Synchronization:
- Automatic user creation in MongoDB
- Profile updates synced in real-time
- User deletion cascades to related data
- Custom user dropdown menu (replaces Clerk
UserButton) - Custom account settings page with:
- Profile management
- Security settings
- Active session viewer
- Connected accounts display
- Danger zone (account deletion)
// Custom auth hook
const { user, isLoaded, isSignedIn } = useUser();
const { signOut } = useClerk();
const { reverify } = useReverification();
// Protected route
<Route element={<ProtectedRoute />}>
<Route path="/profile" element={<Profile />} />
</Route>
// Reverification for sensitive actions
await reverify(async () => {
await user.updatePassword({
currentPassword,
newPassword
});
});{
title: String (required, 5-100 chars),
description: String (required, 20-1000 chars),
category: String (enum: roads, water, electricity, garbage, etc.),
status: String (enum: reported, in-progress, resolved),
images: [{ url, publicId }],
location: {
type: { type: String, default: 'Point' },
coordinates: [Number] // [longitude, latitude]
},
address: String,
reportedBy: { type: ObjectId, ref: 'User' },
upvotes: Number (default: 0),
commentCount: Number (default: 0),
priority: String (enum: low, medium, high),
resolvedAt: Date,
resolvedBy: { type: ObjectId, ref: 'User' },
resolutionNotes: String,
resolutionImages: [{ url, publicId }],
createdAt: Date,
updatedAt: Date
}{
clerkId: String (unique, required),
email: String (required),
firstName: String,
lastName: String,
profileImage: String,
role: String (enum: user, admin),
isActive: Boolean (default: true),
metadata: Object, // Additional Clerk metadata
createdAt: Date,
updatedAt: Date
}{
content: String (required, 1-500 chars),
author: { type: ObjectId, ref: 'User' },
issue: { type: ObjectId, ref: 'Issue' },
createdAt: Date,
updatedAt: Date
}{
user: { type: ObjectId, ref: 'User' },
issue: { type: ObjectId, ref: 'Issue' },
createdAt: Date
}// Geospatial index for location queries
Issue.index({ location: '2dsphere' });
// Text index for search
Issue.index({ title: 'text', description: 'text' });
// Compound index for filtering
Issue.index({ status: 1, category: 1, createdAt: -1 });/* Primary Colors */
--primary-50: #eff6ff;
--primary-500: #3b82f6; /* Main brand color */
--primary-600: #2563eb;
--primary-700: #1d4ed8;
/* Dark Theme */
--dark-900: #0f172a; /* Background */
--dark-800: #1e293b; /* Card background */
--dark-700: #334155; /* Borders */
--dark-600: #475569; /* Muted text */
--dark-400: #94a3b8; /* Secondary text */
--dark-300: #cbd5e1; /* Primary text */
/* Status Colors */
--status-reported: #ef4444; /* Red */
--status-in-progress: #f59e0b; /* Amber */
--status-resolved: #10b981; /* Green */- Font Family: System font stack (San Francisco, Segoe UI, Roboto)
- Headings: Bold, larger sizes with tracking
- Body: Regular, readable line-height (1.6)
- Cards: Rounded corners (12px), subtle shadows, hover effects
- Buttons: Primary (blue), Secondary (gray), Danger (red)
- Forms: Clean inputs with focus states, inline validation
- Modals: Backdrop blur, slide-in animations
- Prepare for deployment
cd client
npm run build- Deploy to Vercel
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Set environment variables in Vercel dashboard- Configure Vercel
- Build Command:
npm run build - Output Directory:
dist - Install Command:
npm install
- Create
render.yaml
services:
- type: web
name: nagarsathi-api
env: node
buildCommand: npm install
startCommand: npm start
envVars:
- key: NODE_ENV
value: production- Deploy to Render
- Connect GitHub repository
- Select
serveras root directory - Add environment variables from dashboard
- Production Database
- Create dedicated cluster for production
- Enable backup and monitoring
- Configure IP whitelist (add deployment server IPs)
- Indexes
# Run in MongoDB shell
db.issues.createIndex({ location: "2dsphere" })
db.issues.createIndex({ status: 1, createdAt: -1 })- Update Clerk webhook URL to production backend
- Configure CORS origins in backend
- Test OAuth flows in production
- Verify Cloudinary uploads work
- Run database migrations if needed
- Test all critical user flows
- Set up error monitoring (Sentry, LogRocket)
- Configure CDN caching rules
- Enable HTTPS/SSL
- Set up automated backups
# Frontend tests
cd client
npm test
# Backend tests
cd server
npm test
# E2E tests
npm run test:e2eWe welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Follow ESLint configuration
- Write meaningful commit messages
- Update documentation for new features
- Test thoroughly before submitting PR
This project is licensed under the MIT License - see the LICENSE file for details.
- Your Name - Initial work - GitHub Profile
See also the list of contributors who participated in this project.
- Clerk team for amazing authentication platform
- Leaflet contributors for the mapping library
- MongoDB Atlas for database hosting
- Cloudinary for image management
- Tailwind CSS team for the utility framework
- React community for excellent ecosystem
For support, email support@nagarsathi.com or join our Slack channel.
- Basic issue reporting
- Map visualization
- Admin dashboard
- Analytics
- Mobile app (React Native)
- Push notifications
- Advanced search
- Export reports
- AI-powered issue categorization
- Sentiment analysis
- Municipality API integration
- Multi-language support
Built with β€οΈ for better communities