Overview
The Location Based Multi-vendor E-commerce System is an innovative web application built using the MERN stack (MongoDB, Express.js, React.js, Node.js). This platform allows multiple vendors to register and sell their products based on the user's location, providing a personalized shopping experience. Ideal for students, this project enhances coding skills, teaches the integration of location-based services, and provides insights into managing multi-vendor environments.
Transform local shopping with intelligent geolocation—connecting customers with nearby vendors for faster delivery and personalized product discovery.
Why Location-Based E-Commerce?
Traditional e-commerce platforms show all products regardless of location, leading to:
- Long Delivery Times: Products shipped from distant locations
- High Shipping Costs: Expensive long-distance delivery
- Irrelevant Products: Items not available locally
- Poor User Experience: Overwhelming product choices
- Vendor Limitations: Small local businesses can't compete
Location-Based Advantages:
- Faster Delivery: Products from nearby vendors arrive quickly
- Lower Costs: Reduced shipping fees for local purchases
- Support Local Business: Connect with neighborhood vendors
- Relevant Products: See what's available in your area
- Real-Time Availability: Know what's in stock nearby
- Community Building: Foster local commerce ecosystems
Key Innovations
1. Geolocation Integration
- User Location Detection: Automatic GPS/IP-based location
- Manual Location Entry: Users can set preferred location
- Radius-Based Search: Find vendors within specified distance
- Real-Time Tracking: Track delivery in real-time
- Multiple Addresses: Save work, home, and custom locations
2. Proximity-Based Discovery
- Nearby Vendors: Discover shops in your vicinity
- Distance Calculation: See exact distance to each vendor
- Sorting by Distance: Products sorted by proximity
- Map View: Visual representation of vendor locations
- Area-Based Filtering: Filter by neighborhood or city
3. Location-Aware Features
- Dynamic Delivery Fees: Calculated based on distance
- Estimated Delivery Time: Based on vendor proximity
- Zone-Based Pricing: Different prices for different areas
- Local Deals: Special offers for nearby customers
- Pickup Options: Collect from nearby vendors
Core Features
For Customers
Location Services
- Auto-Detection: GPS-based location detection
- Search by Address: Enter any location manually
- Saved Locations: Store multiple delivery addresses
- Current Location: Use device GPS
- Location History: Quick access to recent locations
Shopping Experience
- Nearby Products: Browse items from local vendors
- Distance Display: See how far each vendor is
- Map View: Visualize vendor locations on map
- Filter by Distance: Show only vendors within X km
- Sort Options: Distance, price, rating, delivery time
- Local Recommendations: AI-suggested nearby products
Order & Delivery
- Location-Based Pricing: Delivery cost based on distance
- Multiple Delivery Options:
- Home delivery
- Pickup from vendor
- Pickup points
- Real-Time Tracking: Track order on map
- Estimated Arrival: Dynamic ETA based on location
- Delivery Zones: Check if vendor delivers to your area
For Vendors
Store Setup
- Location Registration: Pin exact store location
- Service Area: Define delivery radius
- Multiple Locations: Manage multiple store branches
- Operating Hours: Set location-specific timings
- Geofencing: Set delivery boundaries
Product Management
- Location-Based Inventory: Stock levels per location
- Area-Specific Pricing: Different prices for different zones
- Delivery Zone Setup: Configure where you deliver
- Distance-Based Shipping: Auto-calculate shipping fees
- Local Promotions: Offer deals to nearby customers
Order Management
- Location-Filtered Orders: See orders in your area
- Route Optimization: Best delivery routes
- Distance Analysis: Analytics on customer locations
- Delivery Assignment: Assign drivers by proximity
- Zone Performance: Track sales by area
For Administrators
Platform Management
- Vendor Verification: Verify vendor locations
- Geofence Management: Define service zones
- Analytics Dashboard: Location-based insights
- Heat Maps: Visualize customer/vendor density
- Performance Metrics: Track by region
Location Tools
- Boundary Management: Set city/region boundaries
- Zone Creation: Create delivery zones
- Distance Matrix: Pre-calculate distances
- Location Validation: Verify addresses
- Map Configuration: Customize map settings
Tech Stack
Frontend (React)
- React 18+: Modern UI library
- React Router: Navigation
- Redux Toolkit: State management
- Google Maps React: Map integration
- Leaflet (alternative): Open-source maps
- Geolocation API: Browser location access
- Material-UI/Ant Design: UI components
- Axios: HTTP requests
- Socket.io-client: Real-time tracking
- React Query: Data fetching
Backend (Node.js & Express)
- Node.js 16+: JavaScript runtime
- Express.js: Web framework
- MongoDB & Mongoose: Database with geospatial queries
- JWT: Authentication
- Socket.io: Real-time communication
- Node-Geocoder: Address geocoding
- Geolib: Distance calculations
- Multer: File uploads
- Bcrypt: Password hashing
Geolocation Services
- Google Maps API:
- Maps JavaScript API
- Geocoding API
- Distance Matrix API
- Directions API
- Places API
- OpenStreetMap/Leaflet: Free alternative
- Mapbox: Advanced mapping
Database (MongoDB)
- Geospatial Indexes: For location queries
- 2dsphere Index: Earth-like sphere calculations
- GeoJSON: Store location data
- Aggregation Pipeline: Complex geo queries
Additional Tools
- Redis: Caching location data
- Cloudinary: Image storage
- Twilio: SMS notifications
- Firebase: Push notifications
- PM2: Process management
Project Structure
location-ecommerce/
├─ client/
│ ├─ public/
│ └─ src/
│ ├─ components/
│ │ ├─ maps/
│ │ │ ├─ GoogleMapComponent.jsx
│ │ │ ├─ VendorMap.jsx
│ │ │ ├─ DeliveryTracker.jsx
│ │ │ └─ LocationPicker.jsx
│ │ ├─ location/
│ │ │ ├─ LocationDetector.jsx
│ │ │ ├─ AddressSelector.jsx
│ │ │ ├─ RadiusFilter.jsx
│ │ │ └─ NearbyVendors.jsx
│ │ ├─ customer/
│ │ │ ├─ ProductGrid.jsx
│ │ │ ├─ VendorCard.jsx
│ │ │ ├─ DistanceDisplay.jsx
│ │ │ └─ LocationBasedCheckout.jsx
│ │ ├─ vendor/
│ │ │ ├─ StoreLocation.jsx
│ │ │ ├─ DeliveryZones.jsx
│ │ │ ├─ OrderMap.jsx
│ │ │ └─ AreaAnalytics.jsx
│ │ └─ admin/
│ │ ├─ LocationHeatMap.jsx
│ │ ├─ ZoneManagement.jsx
│ │ └─ VendorVerification.jsx
│ ├─ pages/
│ │ ├─ Home.jsx
│ │ ├─ Browse.jsx
│ │ ├─ VendorDetails.jsx
│ │ ├─ Checkout.jsx
│ │ └─ TrackOrder.jsx
│ ├─ redux/
│ │ ├─ slices/
│ │ │ ├─ locationSlice.js
│ │ │ ├─ vendorSlice.js
│ │ │ └─ orderSlice.js
│ ├─ services/
│ │ ├─ locationService.js
│ │ ├─ mapService.js
│ │ └─ geocodingService.js
│ └─ utils/
│ ├─ distanceCalculator.js
│ ├─ geoUtils.js
│ └─ mapHelpers.js
├─ server/
│ ├─ config/
│ │ ├─ database.js
│ │ ├─ maps.js
│ │ └─ redis.js
│ ├─ models/
│ │ ├─ User.js
│ │ ├─ Vendor.js # With location field
│ │ ├─ Product.js # With vendor location
│ │ ├─ Order.js # With delivery location
│ │ ├─ Location.js # User addresses
│ │ └─ DeliveryZone.js # Vendor delivery areas
│ ├─ controllers/
│ │ ├─ locationController.js
│ │ ├─ vendorController.js
│ │ ├─ productController.js
│ │ └─ orderController.js
│ ├─ routes/
│ │ ├─ location.js
│ │ ├─ vendors.js
│ │ ├─ products.js
│ │ └─ orders.js
│ ├─ middleware/
│ │ ├─ geoLocation.js
│ │ └─ distanceValidator.js
│ ├─ services/
│ │ ├─ geocodingService.js
│ │ ├─ distanceService.js
│ │ ├─ deliveryService.js
│ │ └─ notificationService.js
│ └─ utils/
│ ├─ geoHelpers.js
│ └─ distanceMatrix.js
└─ package.json
Database Schema with Geospatial Support
Vendor Model with Location
const vendorSchema = new mongoose.Schema({
storeName: { type: String, required: true },
owner: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
// Geospatial location using GeoJSON
location: {
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number], // [longitude, latitude]
required: true
}
},
address: {
street: String,
city: String,
state: String,
country: String,
zipCode: String,
formatted: String
},
// Delivery configuration
deliveryRadius: { type: Number, default: 10 }, // km
deliveryZones: [{
name: String,
polygon: {
type: { type: String, enum: ['Polygon'] },
coordinates: [[[Number]]] // GeoJSON polygon
},
deliveryFee: Number
}],
minimumOrder: { type: Number, default: 0 },
freeDeliveryAbove: Number,
operatingHours: [{
day: String,
open: String,
close: String
}],
isActive: { type: Boolean, default: true },
rating: { type: Number, default: 0 },
createdAt: { type: Date, default: Date.now }
});
// Create geospatial index for location-based queries
vendorSchema.index({ location: '2dsphere' });
Product Model
const productSchema = new mongoose.Schema({
vendor: { type: mongoose.Schema.Types.ObjectId, ref: 'Vendor', required: true },
name: { type: String, required: true },
description: String,
price: { type: Number, required: true },
// Location-based pricing
zonePricing: [{
zoneName: String,
price: Number
}],
stock: { type: Number, default: 0 },
images: [String],
category: String,
// Availability by area
availableInZones: [String],
createdAt: { type: Date, default: Date.now }
});
Order Model with Delivery Location
const orderSchema = new mongoose.Schema({
customer: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
vendor: { type: mongoose.Schema.Types.ObjectId, ref: 'Vendor' },
items: [{
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' },
quantity: Number,
price: Number
}],
// Delivery location
deliveryLocation: {
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
},
deliveryAddress: {
street: String,
city: String,
zipCode: String,
formatted: String
},
// Distance and delivery info
distanceFromVendor: Number, // km
estimatedDeliveryTime: Number, // minutes
deliveryFee: Number,
// Current delivery location (for tracking)
currentLocation: {
type: { type: String, enum: ['Point'] },
coordinates: [Number]
},
status: {
type: String,
enum: ['pending', 'confirmed', 'preparing', 'out-for-delivery', 'delivered', 'cancelled'],
default: 'pending'
},
total: Number,
orderDate: { type: Date, default: Date.now },
deliveredAt: Date
});
orderSchema.index({ deliveryLocation: '2dsphere' });
orderSchema.index({ currentLocation: '2dsphere' });
Location-Based Queries
Finding Nearby Vendors
// Find vendors within radius
const findNearbyVendors = async (longitude, latitude, radiusKm = 10) => {
const vendors = await Vendor.find({
location: {
$near: {
$geometry: {
type: 'Point',
coordinates: [longitude, latitude]
},
$maxDistance: radiusKm * 1000 // Convert km to meters
}
},
isActive: true
});
return vendors;
};
Calculating Distance
const calculateDistance = async (vendorId, userLocation) => {
const vendor = await Vendor.findById(vendorId);
const distance = geolib.getDistance(
{
latitude: userLocation.coordinates[1],
longitude: userLocation.coordinates[0]
},
{
latitude: vendor.location.coordinates[1],
longitude: vendor.location.coordinates[0]
}
);
return distance / 1000; // Convert to km
};
Products from Nearby Vendors
const getNearbyProducts = async (req, res) => {
const { longitude, latitude, radius = 10 } = req.query;
// First find nearby vendors
const nearbyVendors = await Vendor.find({
location: {
$near: {
$geometry: {
type: 'Point',
coordinates: [parseFloat(longitude), parseFloat(latitude)]
},
$maxDistance: radius * 1000
}
}
});
const vendorIds = nearbyVendors.map(v => v._id);
// Get products from these vendors
const products = await Product.find({
vendor: { $in: vendorIds },
stock: { $gt: 0 }
}).populate('vendor');
// Add distance to each product
const productsWithDistance = products.map(product => {
const distance = geolib.getDistance(
{ latitude, longitude },
{
latitude: product.vendor.location.coordinates[1],
longitude: product.vendor.location.coordinates[0]
}
) / 1000;
return {
...product.toObject(),
distance: distance.toFixed(2)
};
});
// Sort by distance
productsWithDistance.sort((a, b) => a.distance - b.distance);
res.json(productsWithDistance);
};
Frontend Implementation
Location Detection Component
import React, { useState, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { setUserLocation } from '../redux/slices/locationSlice';
const LocationDetector = () => {
const [loading, setLoading] = useState(false);
const dispatch = useDispatch();
const detectLocation = () => {
setLoading(true);
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const location = {
latitude: position.coords.latitude,
longitude: position.coords.longitude
};
dispatch(setUserLocation(location));
// Reverse geocode to get address
reverseGeocode(location);
setLoading(false);
},
(error) => {
console.error('Location error:', error);
setLoading(false);
}
);
}
};
return (
<button onClick={detectLocation} disabled={loading}>
{loading ? 'Detecting...' : 'Use Current Location'}
</button>
);
};
Google Maps Integration
import React from 'react';
import { GoogleMap, Marker, Circle, useLoadScript } from '@react-google-maps/api';
const VendorMap = ({ vendors, userLocation, radius }) => {
const { isLoaded } = useLoadScript({
googleMapsApiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY
});
if (!isLoaded) return <div>Loading map...</div>;
return (
<GoogleMap
zoom={12}
center={userLocation}
mapContainerStyle={{ width: '100%', height: '500px' }}
>
{/* User location marker */}
<Marker
position={userLocation}
icon={{ url: '/user-pin.png' }}
/>
{/* Search radius circle */}
<Circle
center={userLocation}
radius={radius * 1000} // Convert km to meters
options={{
fillColor: '#4285F4',
fillOpacity: 0.1,
strokeColor: '#4285F4',
strokeOpacity: 0.5
}}
/>
{/* Vendor markers */}
{vendors.map(vendor => (
<Marker
key={vendor._id}
position={{
lat: vendor.location.coordinates[1],
lng: vendor.location.coordinates[0]
}}
icon={{ url: '/store-pin.png' }}
title={vendor.storeName}
/>
))}
</GoogleMap>
);
};
Distance-Based Delivery Fee
const calculateDeliveryFee = (distance, vendor) => {
if (distance > vendor.deliveryRadius) {
return null; // Outside delivery area
}
// Check if eligible for free delivery
if (vendor.freeDeliveryAbove && cartTotal >= vendor.freeDeliveryAbove) {
return 0;
}
// Base fee + per km charge
const baseFee = 2.00;
const perKmCharge = 0.50;
return baseFee + (distance * perKmCharge);
};
Setup & Installation
Prerequisites
- Node.js 16+
- MongoDB (with geospatial support)
- Google Maps API key
- Redis (optional)
Installation Steps
1. Clone and Install
git clone <repository-url>
cd location-ecommerce
# Install server dependencies
cd server
npm install
# Install client dependencies
cd ../client
npm install
2. Get Google Maps API Key
- Go to Google Cloud Console
- Create new project
- Enable APIs:
- Maps JavaScript API
- Geocoding API
- Distance Matrix API
- Places API
- Create credentials (API key)
- Restrict key (optional but recommended)
3. Configure Environment Variables
server/.env
:
PORT=5000
NODE_ENV=development
# Database
MONGO_URI=mongodb://localhost:27017/location-ecommerce
# JWT
JWT_SECRET=your-jwt-secret
JWT_EXPIRE=7d
# Google Maps
GOOGLE_MAPS_API_KEY=your-google-maps-api-key
# Default location (fallback)
DEFAULT_LATITUDE=40.7128
DEFAULT_LONGITUDE=-74.0060
# Delivery settings
MAX_DELIVERY_RADIUS=50
DEFAULT_DELIVERY_RADIUS=10
# Redis (optional)
REDIS_URL=redis://localhost:6379
# Client URL
CLIENT_URL=http://localhost:3000
client/.env
:
REACT_APP_API_URL=http://localhost:5000/api
REACT_APP_GOOGLE_MAPS_API_KEY=your-google-maps-api-key
REACT_APP_DEFAULT_RADIUS=10
4. Start Servers
# Terminal 1: Start backend
cd server
npm run dev
# Terminal 2: Start frontend
cd client
npm start
Access at:
- Frontend: http://localhost:3000
- Backend: http://localhost:5000
API Endpoints
Location
GET /api/location/detect # Detect IP-based location
POST /api/location/geocode # Convert address to coordinates
POST /api/location/reverse # Convert coordinates to address
GET /api/location/nearby-vendors # Get vendors within radius
Vendors
GET /api/vendors/nearby # Get nearby vendors
GET /api/vendors/:id # Get vendor details
GET /api/vendors/:id/distance # Calculate distance to vendor
POST /api/vendors/register # Register new vendor
PUT /api/vendors/:id/location # Update vendor location
PUT /api/vendors/:id/zones # Update delivery zones
Products
GET /api/products/nearby # Products from nearby vendors
GET /api/products/vendor/:id # Products from specific vendor
GET /api/products/:id # Product details with distance
Orders
POST /api/orders/calculate-fee # Calculate delivery fee
POST /api/orders # Create order
GET /api/orders/:id/track # Track order location
PUT /api/orders/:id/location # Update delivery location
Key Features Implementation
1. Radius-Based Search
const RadiusFilter = () => {
const [radius, setRadius] = useState(10);
const dispatch = useDispatch();
const handleRadiusChange = (newRadius) => {
setRadius(newRadius);
dispatch(updateSearchRadius(newRadius));
dispatch(fetchNearbyVendors());
};
return (
<div>
<label>Search Radius: {radius} km</label>
<input
type="range"
min="1"
max="50"
value={radius}
onChange={(e) => handleRadiusChange(e.target.value)}
/>
</div>
);
};
2. Real-Time Order Tracking
// Backend: Update delivery location
socket.on('update-location', async (data) => {
const { orderId, latitude, longitude } = data;
await Order.findByIdAndUpdate(orderId, {
currentLocation: {
type: 'Point',
coordinates: [longitude, latitude]
}
});
// Emit to customer
socket.to(orderId).emit('location-updated', { latitude, longitude });
});
// Frontend: Display tracking
const OrderTracking = ({ orderId }) => {
const [deliveryLocation, setDeliveryLocation] = useState(null);
useEffect(() => {
socket.on('location-updated', (location) => {
setDeliveryLocation(location);
});
return () => socket.off('location-updated');
}, []);
return (
<GoogleMap center={deliveryLocation}>
<Marker position={deliveryLocation} icon="/delivery-truck.png" />
</GoogleMap>
);
};
3. Delivery Zone Validation
const checkDeliveryAvailability = async (vendorId, deliveryLocation) => {
const vendor = await Vendor.findById(vendorId);
// Check if within delivery radius
const distance = calculateDistance(
vendor.location.coordinates,
deliveryLocation.coordinates
);
if (distance > vendor.deliveryRadius) {
return { available: false, reason: 'Outside delivery radius' };
}
// Check specific delivery zones
const inZone = vendor.deliveryZones.some(zone => {
return pointInPolygon(
deliveryLocation.coordinates,
zone.polygon.coordinates[0]
);
});
if (!inZone && vendor.deliveryZones.length > 0) {
return { available: false, reason: 'Not in delivery zone' };
}
return { available: true, distance };
};
Learning Outcomes
Geolocation Services
- Google Maps API: Integration and usage
- Geospatial Queries: MongoDB geo queries
- Distance Calculation: Haversine formula
- Geocoding: Address to coordinates
- Reverse Geocoding: Coordinates to address
MERN Stack Development
- React: Component-based UI
- Node.js/Express: RESTful APIs
- MongoDB: Geospatial indexing
- Real-Time: Socket.io integration
Advanced Features
- Map Integration: Google Maps/Leaflet
- Location Tracking: GPS and real-time updates
- Proximity Search: Efficient geo queries
- Zone Management: Polygon boundaries
Performance Optimization
Caching Location Data
// Cache vendor locations in Redis
const cacheVendorLocations = async () => {
const vendors = await Vendor.find({}, 'location storeName');
await redis.set(
'vendor-locations',
JSON.stringify(vendors),
'EX',
3600 // 1 hour
);
};
Geospatial Indexing
// Create compound index for faster queries
vendorSchema.index({ location: '2dsphere', isActive: 1 });
productSchema.index({ vendor: 1, stock: 1 });
Deployment
Environment-Specific Settings
- Development: Use test API keys
- Production: Restricted API keys
- Configure CORS properly
- Enable SSL/HTTPS
- Set up CDN for maps
Monitoring
- Track API usage (Google Maps)
- Monitor query performance
- Log location errors
- Analytics on user locations
Use Cases
Academic Projects
- Final year project
- Geolocation learning
- MERN stack mastery
- Maps integration
Real-World Applications
- Local marketplaces
- Food delivery apps
- Grocery platforms
- Service provider networks
- Hyperlocal commerce
Portfolio
- Advanced MERN skills
- Maps API integration
- Real-time features
- Complex database queries
Conclusion
The Location Based Multi-Vendor E-Commerce System represents the future of local commerce, combining the power of geolocation with multi-vendor marketplace functionality. By leveraging the MERN stack and Google Maps API, this project provides students with comprehensive experience in building location-aware applications.
This system goes beyond traditional e-commerce by creating personalized, proximity-based shopping experiences that benefit both customers and vendors. Customers enjoy faster delivery and support local businesses, while vendors can reach nearby customers efficiently.
For students, this project offers invaluable learning opportunities in React frontend development with maps, Node.js backend with geospatial queries, MongoDB geo indexing, and real-time tracking. The practical applications range from food delivery to hyperlocal marketplaces, making it highly relevant for modern e-commerce.
Whether you're building a portfolio, completing an academic project, or exploring location-based services, this platform provides a solid foundation for understanding geolocation integration, proximity search, and scalable multi-vendor systems. Master the MERN stack while creating innovative, location-aware solutions that connect local communities!