Add Live Realtime Data in Maptoolkit Maps JS
Keeping a map layer in sync with a live data feed requires periodic fetching and calling setData on the GeoJSON source to push new features to the renderer. This example polls an external API every few seconds and updates a symbol layer to reflect the latest positions. Use this pattern for tracking vehicles, displaying live sensor readings, or any application where map data changes frequently.
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
zoom: 2,
attributionControl: { compact: false }
});
map.addControl(new maptoolkit.NavigationControl(), 'top-right');
map.on('load', () => {
map.addSource('drone', {
type: 'geojson',
data: {
type: 'Feature',
geometry: { type: 'Point', coordinates: [0, 0] }
}
});
map.addLayer({
id: 'drone',
type: 'circle',
source: 'drone',
paint: {
'circle-radius': 10,
'circle-color': '#ee4b2b',
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff'
}
});
window.setInterval(() => {
fetch('https://www.random.org/decimal-fractions/?num=2&dec=10&col=1&format=plain&rnd=new')
.then(r => r.text())
.then(text => {
const coordinates = text.trim().split('\n').map(l => (Number(l) * 180) - 90);
const json = {
type: 'Feature',
geometry: { type: 'Point', coordinates }
};
map.getSource('drone').setData(json);
map.flyTo({ center: coordinates, speed: 0.5 });
});
}, 2000);
});<!DOCTYPE html>
<html lang="en">
<head>
<title>Add Live Realtime Data - Maptoolkit Maps JS</title>
<meta property="og:description" content="Use realtime data streams to move a symbol on your map." />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
zoom: 2,
attributionControl: { compact: false }
});
map.addControl(new maptoolkit.NavigationControl(), 'top-right');
map.on('load', () => {
map.addSource('drone', {
type: 'geojson',
data: {
type: 'Feature',
geometry: { type: 'Point', coordinates: [0, 0] }
}
});
map.addLayer({
id: 'drone',
type: 'circle',
source: 'drone',
paint: {
'circle-radius': 10,
'circle-color': '#ee4b2b',
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff'
}
});
window.setInterval(() => {
fetch('https://www.random.org/decimal-fractions/?num=2&dec=10&col=1&format=plain&rnd=new')
.then(r => r.text())
.then(text => {
const coordinates = text.trim().split('\n').map(l => (Number(l) * 180) - 90);
const json = {
type: 'Feature',
geometry: { type: 'Point', coordinates }
};
map.getSource('drone').setData(json);
map.flyTo({ center: coordinates, speed: 0.5 });
});
}, 2000);
});
</script>
</body>
</html>Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.
How it works
A GeoJSON source has no incremental update path. You replace the whole payload
with setData and the renderer diffs it, so there is no “move one feature” call to look
for.
The loop is: fetch, build a new FeatureCollection, call setData. Everything else stays put,
including the layer, its paint properties and the camera.
Polling on a timer is the simplest version and the one shown here. For a real feed, a
WebSocket or server-sent events avoid the delay between a change and the next poll, and the
setData call at the end is identical either way.
Watch the update rate against the payload size. Replacing a large collection many times a second re-parses and re-uploads all of it; sending only what changed and merging client-side is the usual fix.
Next steps
A live feed usually needs history as well as a current position. Keeping a trail of recent points, and drawing it as a line that grows, turns a dot into something you can read at a glance.
Following is the other decision: whether the camera tracks the feature, and what happens when the user pans away. Most tracking maps end up with a follow mode the user can break and resume.