A full-stack web application for exploring Indian pincodes, built with React (frontend) and Express + MongoDB (backend). Search by pincode or city name, browse all states and districts, compare pincodes side-by-side, do bulk lookups, and view rich analytics — all in a sleek dark UI.
| Feature | Description |
|---|---|
| 📍 Pincode Lookup | Search any 6-digit pincode for city, district, state, offices |
| 🔍 Explore Pincodes | Browse and filter by state → district → taluk with paginated results |
| 📊 Dashboard | Overview with stat cards, state-wise bar chart, delivery pie chart |
| 🔍 City Search | Find pincodes by city, district or post office name |
| 📋 Bulk Lookup | Look up up to 50 pincodes at once |
| ⚖️ Compare | Side-by-side pincode comparison with match/mismatch highlight |
| 🗺️ Browse States | Explore all states → districts → cities |
| 📊 Analytics | Charts and stats — offices per state, office types, delivery status |
| ℹ️ About | Feature overview, tech stack, and API endpoint reference |
| 🔁 Autocomplete | Live suggestions as you type |
| 📍 Nearby Pincodes | Find pincodes in the same district |
| ⬇️ CSV Export | Export any result set as a CSV file |
| 🔗 Share Links | Copy a shareable URL for any pincode |
| 🌙 Dark / Light Mode | Toggle and persists across sessions |
| 🕓 Search History | Recent pincode searches saved locally |
pinexplorer/
├── server.js # Express entry point
├── config/
│ └── db.js # MongoDB connection configuration
├── models/
│ └── Pincode.js # Mongoose schema and model
├── controllers/
│ └── pincodeController.js # All route handler logic
├── routes/
│ └── pincodeRoutes.js # API route definitions
├── frontend/ # React + Vite frontend
├── package.json
└── README.md
Make sure you have the following installed:
- Node.js v18 or above
- MongoDB running locally on port
27017 - A MongoDB database named
Pincode1with a collection namedpincodespopulated with Indian pincode data
Each document in the pincodes collection should look like this:
{
"officeName": "Andheri S.O",
"pincode": 400053,
"officeType": "Sub Post Office",
"deliveryStatus": "Delivery",
"divisionName": "Mumbai City",
"regionName": "Mumbai",
"circleName": "Maharashtra",
"taluk": "Andheri",
"districtName": "Mumbai",
"stateName": "MAHARASHTRA"
}You can find free Indian pincode datasets on data.gov.in or GitHub.
git clone https://github.com/yourusername/pinexplorer.git
cd pinexplorercd Project
npm installCreate a .env file in the Project/ directory:
PORT=5000
MONGODB_URI=your_mongodb_connection_stringIf
MONGODB_URIis not provided, the app uses the default MongoDB Atlas connection.
npm startOr for development:
npm run devYou should see:
MongoDB Connected
Server running on port 5000
cd frontend
npm install
npm run devThe frontend will be available at http://localhost:5173.
Base URL: http://localhost:5000
Look up a single pincode.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
code |
number | ✅ | 6-digit Indian pincode |
Example Request
GET /api/pincode?code=400001
Example Response
{
"success": true,
"cityDetails": {
"pincode": 400001,
"city": "Mumbai",
"district": "Mumbai",
"state": "MAHARASHTRA",
"region": "Mumbai",
"division": "Mumbai City",
"circle": "Maharashtra",
"totalOffices": 5,
"offices": [
{ "name": "Fort S.O", "type": "Sub Post Office", "deliveryStatus": "Delivery" }
]
}
}Search for pincodes by city name, district, or post office name.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
q |
string | ✅ | Search query (min 2 characters) |
type |
string | ❌ | all (default), city, district, or office |
Example Request
GET /api/search?q=Bandra&type=city
Example Response
{
"success": true,
"query": "Bandra",
"total": 3,
"results": [
{
"pincode": 400050,
"city": "Bandra",
"district": "Mumbai",
"state": "MAHARASHTRA",
"region": "Mumbai",
"officeCount": 4
}
]
}Get live autocomplete suggestions for city and district names.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
q |
string | ✅ | Partial query (min 2 characters) |
Example Request
GET /api/autocomplete?q=Pune
Example Response
{
"success": true,
"suggestions": [
{ "label": "Pune", "type": "city" },
{ "label": "Pune City", "type": "district" }
]
}Find other pincodes in the same district as the given pincode.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
pincode |
number | ✅ | The base 6-digit pincode |
Example Request
GET /api/nearby?pincode=400001
Example Response
{
"success": true,
"basePincode": 400001,
"baseDistrict": "Mumbai",
"total": 12,
"nearby": [
{ "pincode": 400002, "city": "Kalbadevi", "district": "Mumbai", "state": "MAHARASHTRA", "officeCount": 3 }
]
}Look up multiple pincodes in a single request.
Request Body
{
"pincodes": [400001, 110001, 600001]
}Maximum 50 pincodes per request.
Example Response
{
"success": true,
"found": [
{
"pincode": 400001,
"city": "Mumbai",
"district": "Mumbai",
"state": "MAHARASHTRA",
"region": "Mumbai",
"division": "Mumbai City",
"officeCount": 5,
"offices": ["Fort S.O", "GPO"]
}
],
"notFound": [999999]
}Get aggregated analytics across all pincodes in the database.
Example Response
{
"success": true,
"summary": {
"totalOffices": 154000,
"totalPincodes": 19000,
"totalStates": 36,
"totalDistricts": 720
},
"stateStats": [
{ "state": "UTTAR PRADESH", "totalOffices": 18000, "uniquePincodes": 2200, "uniqueDistricts": 75 }
],
"officeTypes": [
{ "type": "Sub Post Office", "count": 130000 },
{ "type": "Head Post Office", "count": 900 }
],
"deliveryStatus": [
{ "status": "Delivery", "count": 90000 },
{ "status": "Non-Delivery", "count": 64000 }
]
}Get a sorted list of all states in the database.
Example Response
{
"success": true,
"totalStates": 36,
"states": ["ANDHRA PRADESH", "ASSAM", "BIHAR", ...]
}Get all districts and cities for a given state.
URL Parameters
| Param | Type | Description |
|---|---|---|
state_name |
string | State name (case-insensitive) |
Example Request
GET /states/MAHARASHTRA
Example Response
{
"success": true,
"state": "MAHARASHTRA",
"totalDistricts": 36,
"districts": [
{
"district": "Mumbai",
"cities": ["Andheri", "Bandra", "Colaba", "Kurla"]
}
]
}Get a sorted array of all unique state names.
Example Request
GET /api/states
Example Response
[
"ANDHRA PRADESH",
"GUJARAT",
"MAHARASHTRA",
"TAMIL NADU"
]Get all districts for a given state.
URL Parameters
| Param | Type | Description |
|---|---|---|
state |
string | State name (case-insensitive) |
Example Request
GET /api/states/GUJARAT/districts
Example Response
[
"AHMEDABAD",
"SURAT",
"VADODARA"
]Get all taluks for a given state and district.
URL Parameters
| Param | Type | Description |
|---|---|---|
state |
string | State name |
district |
string | District name |
Example Request
GET /api/states/GUJARAT/districts/AHMEDABAD/taluks
Example Response
[
"AHMEDABAD CITY",
"DASKROI",
"SANAND"
]Get filtered and paginated pincode data.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
state |
string | ❌ | Filter by state |
district |
string | ❌ | Filter by district |
taluk |
string | ❌ | Filter by taluk |
page |
number | ❌ | Page number (default: 1) |
limit |
number | ❌ | Results per page (default: 20) |
Example Request
GET /api/pincodes?state=GUJARAT&district=AHMEDABAD&taluk=DASKROI&page=1&limit=20
Example Response
{
"data": [
{
"pincode": 382425,
"officeName": "Daskroi S.O",
"officeType": "Sub Post Office",
"deliveryStatus": "Delivery",
"taluk": "DASKROI",
"district": "AHMEDABAD",
"state": "GUJARAT",
"division": "Ahmedabad",
"region": "Rajkot",
"circle": "Gujarat"
}
],
"total": 120,
"page": 1,
"limit": 20
}Look up a single pincode by path parameter.
URL Parameters
| Param | Type | Description |
|---|---|---|
pincode |
number | 6-digit Indian pincode |
Example Request
GET /api/pincode/400001
Example Response
{
"success": true,
"cityDetails": {
"pincode": 400001,
"city": "Mumbai",
"district": "Mumbai",
"state": "MAHARASHTRA",
"region": "Mumbai",
"division": "Mumbai City",
"circle": "Maharashtra",
"totalOffices": 5,
"offices": [
{ "name": "Fort S.O", "type": "Sub Post Office", "deliveryStatus": "Delivery" }
]
}
}Get state-wise office count distribution for bar charts.
Example Request
GET /api/stats/state-distribution
Example Response
[
{ "state": "GUJARAT", "count": 12000 },
{ "state": "MAHARASHTRA", "count": 20000 },
{ "state": "TAMIL NADU", "count": 15000 }
]Get delivery vs non-delivery office counts for pie charts.
Example Request
GET /api/stats/delivery-distribution
Example Response
{
"delivery": 120000,
"nonDelivery": 34000
}Export pincode data as a CSV file.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
state |
string | ❌ | Filter by state |
district |
string | ❌ | Filter by district |
taluk |
string | ❌ | Filter by taluk |
Example Request
GET /api/export?state=GUJARAT
Returns a CSV file download with columns: Pincode, Office Name, Office Type, Delivery Status, Taluk, District, State, Division, Region, Circle.
- Node.js — Runtime
- Express.js — Web framework
- Mongoose — MongoDB ODM
- CORS — Cross-origin requests
The backend follows the MVC (Model-View-Controller) pattern:
| Directory | Purpose |
|---|---|
config/ |
Database connection and app configuration |
models/ |
Mongoose schemas and models |
controllers/ |
Business logic and request handlers |
routes/ |
API route definitions mapped to controllers |
server.js |
Express app entry point and middleware setup |
- React — UI framework
- Recharts — Charts and data visualizations
- Google Fonts — Clash Display + Cabinet Grotesk
- CSS Variables — Theming (dark/light mode)
- localStorage — Persistent search history and theme preference
npm install express mongoose corscd frontend
npm installNo other third-party UI libraries are used in the frontend — the entire UI is hand-crafted with CSS.
The backend creates the following MongoDB indexes automatically on startup for fast queries:
pincodeSchema.index({ pincode: 1 });
pincodeSchema.index({ stateName: 1 });
pincodeSchema.index({ districtName: 1 });
pincodeSchema.index({ taluk: 1 });
pincodeSchema.index({ officeName: "text", taluk: "text", districtName: "text" });The app uses these environment variables. Create a .env file in the Project/ directory:
| Variable | Default | Description |
|---|---|---|
MONGODB_URI |
MongoDB Atlas connection string | Database connection |
PORT |
5000 |
Express server port |
Example .env:
PORT=5000
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/PincodeThe database connection is managed in config/db.js and the server listens on the configured port via server.js.
- The map view links out to OpenStreetMap rather than embedding an interactive map. To embed a real interactive map, integrate Leaflet.js with geocoding via the Nominatim API.
- The
/api/statsendpoint queries the full collection — on large datasets (150k+ documents) it may be slow on first load. Consider adding a Redis cache or pre-computing stats on a schedule. - Bulk lookup is capped at 50 pincodes per request to protect server performance.
- Search autocomplete triggers on 2+ characters; very short queries may return many results.
- Add Redis caching for
/api/statsand/states - Add pagination to
/api/searchresults - Embed Leaflet.js for a real interactive map with markers
- Add a PWA manifest + service worker for offline support
- Implement rate limiting with
express-rate-limit - Add input sanitization and helmet.js for security headers
- Write unit tests with Jest (backend) and React Testing Library (frontend)
- Deploy backend to Railway or Render; frontend to Vercel or Netlify
MIT — free to use, modify and distribute.
- Indian pincode data sourced from India Post / data.gov.in
- Charts powered by Recharts
- Map links powered by OpenStreetMap
- Typography: Clash Display + Cabinet Grotesk via Google Fonts