Build a powerful map application with Lovable using our step‐by‐step guide. Discover essential techniques, integration tips, and best practices for your project.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Setting Up Your Lovable Map Application Project
index.html
file and a map.js
file.
Adding the Lovable Library Dependency
index.html
file and insert the following code inside the <head>
section. This code links to the Lovable Map library along with its CSS and JavaScript files via a CDN:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Map Application with Lovable</title>
<!-- Lovable Map Library Dependency -->
<link rel="stylesheet" href="https://cdn.lovablemaps.com/lovable.css">
<script src="https://cdn.lovablemaps.com/lovable.js"></script>
<style>
/_ Custom styles for the map container _/
#map {
width: 100%;
height: 500px;
}
</style>
</head>
<body>
<!-- Map container -->
<div id="map"></div>
<script src="map.js"></script>
</body>
</html>
Creating the Map Initialization Script
map.js
in your project’s file explorer.map.js
. This script initializes the map by invoking Lovable’s API. It sets the initial center to San Francisco and adds a marker at that location:
// Ensure the DOM is fully loaded before initializing the map
document.addEventListener('DOMContentLoaded', function() {
// Initialize a new map instance in the 'map' div
var map = new LovableMap('map', {
center: [37.7749, -122.4194], // Coordinates for San Francisco
zoom: 12 // Initial zoom level
});
// Add a marker at the map center
map.addMarker({
position: [37.7749, -122.4194],
title: "Start Location"
});
// You can further customize the map here (e.g., add layers or controls)
});
Customizing Your Map Features
map.js
after the initial setup. For example, add a button that centers the map back to the original coordinates:
// Create a custom control button to recenter the map
var recenterButton = document.createElement('button');
recenterButton.innerText = 'Recenter Map';
recenterButton.style.position = 'absolute';
recenterButton.style.top = '10px';
recenterButton.style.right = '10px';
recenterButton.onclick = function() {
map.setCenter([37.7749, -122.4194]);
};
document.body.appendChild(recenterButton);
Testing Your Map Application
index.html
and map.js
, use Lovable’s built-in preview function to open your project.
Deploying Your Map Application
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
const mapData = [
{ id: 1, name: 'Central Park', coordinates: { lat: 40.785091, lng: -73.968285 } },
{ id: 2, name: 'Statue of Liberty', coordinates: { lat: 40.689247, lng: -74.044502 } },
{ id: 3, name: 'Times Square', coordinates: { lat: 40.758896, lng: -73.985130 } },
// ... potentially more data points
];
function haversineDistance(coord1, coord2) {
const toRad = (x) => x \* Math.PI / 180;
const R = 6371; // Earth's radius in kilometers
const dLat = toRad(coord2.lat - coord1.lat);
const dLng = toRad(coord2.lng - coord1.lng);
const a = Math.sin(dLat / 2) \* Math.sin(dLat / 2) +
Math.cos(toRad(coord1.lat)) _ Math.cos(toRad(coord2.lat)) _
Math.sin(dLng / 2) \* Math.sin(dLng / 2);
const c = 2 \* Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R \* c;
}
app.post('/api/map/points', (req, res) => {
const { latitude, longitude, radius } = req.body;
if (typeof latitude !== 'number' || typeof longitude !== 'number' || typeof radius !== 'number') {
return res.status(400).json({ error: 'Invalid parameters. Expect latitude, longitude, and radius as numbers.' });
}
const center = { lat: latitude, lng: longitude };
const nearbyPoints = mapData.filter(point => haversineDistance(center, point.coordinates) <= radius);
// Structure the result for the Lovable mapping library
const structuredData = {
center,
radius,
points: nearbyPoints.map(point => ({
id: point.id,
label: point.name,
location: point.coordinates
}))
};
res.json(structuredData);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Map API server running on port ${PORT}`);
});
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
const GEOCODE_API_KEY = process.env.GEOCODE_API_KEY;
const GEOCODE_API_URL = 'https://api.opencagedata.com/geocode/v1/json';
app.post('/api/map/geocode', async (req, res) => {
const { address, extraData } = req.body;
if (!address) {
return res.status(400).json({ error: 'Address parameter is required.' });
}
try {
const response = await axios.get(GEOCODE_API_URL, {
params: { q: address, key: GEOCODE_API_KEY, limit: 1 }
});
if (!response.data.results || response.data.results.length === 0) {
return res.status(404).json({ error: 'No geocoding results found.' });
}
const { lat, lng } = response.data.results[0].geometry;
const lovableData = {
id: Date.now(),
label: address,
location: { lat, lng },
extra: extraData || {}
};
res.json({ success: true, point: lovableData });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => console.log(`Server listening on port ${PORT}`));
const express = require('express');
const app = express();
app.use(express.json());
function calculateDistance(p1, p2) {
const R = 6371; // Earth's radius in km
const dLat = (p2.lat - p1.lat) \* Math.PI / 180;
const dLng = (p2.lng - p1.lng) \* Math.PI / 180;
const a = Math.sin(dLat/2) \* Math.sin(dLat/2) +
Math.cos(p1.lat _ Math.PI/180) _ Math.cos(p2.lat _ Math.PI/180) _
Math.sin(dLng/2) \* Math.sin(dLng/2);
const c = 2 \* Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R \* c;
}
function greedyRoute(points) {
if (points.length === 0) return [];
const route = [];
let current = points[0];
const remaining = points.slice(1);
route.push(current);
while (remaining.length) {
let nearestIndex = 0;
let nearestDistance = calculateDistance(current, remaining[0]);
for (let i = 1; i < remaining.length; i++) {
const dist = calculateDistance(current, remaining[i]);
if (dist < nearestDistance) {
nearestDistance = dist;
nearestIndex = i;
}
}
current = remaining.splice(nearestIndex, 1)[0];
route.push(current);
}
return route;
}
app.post('/api/map/optimized-route', (req, res) => {
const { points } = req.body;
if (!Array.isArray(points) || points.length === 0) {
return res.status(400).json({ error: 'Points array required with at least one point.' });
}
for (const pt of points) {
if (typeof pt.id !== 'number' || typeof pt.lat !== 'number' || typeof pt.lng !== 'number') {
return res.status(400).json({ error: 'Each point must have id, lat, and lng as numbers.' });
}
}
const optimized = greedyRoute(points);
const routeData = {
start: optimized[0],
orderedPoints: optimized.map(pt => ({
id: pt.id,
label: `Location ${pt.id}`,
location: { lat: pt.lat, lng: pt.lng }
}))
};
res.json(routeData);
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Route optimization server running on port ${PORT}`));
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Understanding Requirements and Objectives
Researching and Selecting AI Code Generators
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.