Logo
All Projects
14 min read
merngeolocationecommercereactnodejsmongodbmaps

Location Based Multi-Vendor E-Commerce System using MERN

An innovative MERN stack platform enabling vendors to sell products based on user location, providing personalized shopping experiences with geolocation services.

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

  1. Go to Google Cloud Console
  2. Create new project
  3. Enable APIs:
    • Maps JavaScript API
    • Geocoding API
    • Distance Matrix API
    • Places API
  4. Create credentials (API key)
  5. 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:

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

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!

Share your thoughts

Love to hear from you

Please get in touch with us for inquiries. Whether you have questions or need information. We value your engagement and look forward to assisting you.

Contact Us

Contact us to seek help from us, we will help you as soon as possible

contact@projectmart.in
Send Mail
Customer Service

Contact us to seek help from us, we will help you as soon as possible

+91 7676409450
Text Now

Get in touch

Our friendly team would love to hear from you.