Add an editable dataset in Mapbox GL JS
Copy JavaScript and React examples for loading a published dataset revision as GeoJSON from the Mappinest Dataset API in Mapbox GL JS.
Overview
This guide shows how to fetch the latest published dataset revision as one GeoJSON FeatureCollection and render it in Mapbox GL JS. Use this path when the full dataset fits your application flow and you want to manage supported features in Dataset Studio.
Create a dataset from .geojson or .json in Datasets, or start drawing in Studio. The examples use the `mappinest.world-cities` sample. Copy the owner-scoped Dataset ID from the Datasets page when working with your own data.
API key scopes
The browser API key needs datasets:read. The examples also use the light map style as a background, so add maps:read when the key has explicit scopes. Add every development and production origin to the allowed-domain policy.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Mappinest Dataset GeoJSON with Mapbox GL JS</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v3.16.0/mapbox-gl.css" rel="stylesheet" />
<style>
body { margin: 0; }
#map { height: 100vh; width: 100vw; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://api.mapbox.com/mapbox-gl-js/v3.16.0/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
const apiKey = 'YOUR_MAPPINEST_KEY';
const datasetId = 'mappinest.world-cities';
const map = new mapboxgl.Map({
container: 'map',
style: `https://api.mappinest.com/v1/maps/light/style.json?key=${apiKey}`,
center: [0, 20],
zoom: 2
});
map.addControl(new mapboxgl.NavigationControl(), 'top-right');
map.on('load', async () => {
const response = await fetch(
`https://api.mappinest.com/v1/datasets/${datasetId}.geojson?key=${encodeURIComponent(apiKey)}`
);
if (!response.ok) {
throw new Error('Dataset GeoJSON request failed.');
}
map.addSource('mappinest-dataset', {
type: 'geojson',
data: await response.json()
});
map.addLayer({
id: 'dataset-points',
type: 'circle',
source: 'mappinest-dataset',
paint: {
'circle-color': '#2563eb',
'circle-radius': 6,
'circle-stroke-color': '#ffffff',
'circle-stroke-width': 1.5
}
});
});
</script>
</body>
</html>import { useEffect, useRef } from 'react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
const apiKey = 'YOUR_MAPPINEST_KEY';
const datasetId = 'mappinest.world-cities';
export default function MappinestMapboxDatasetMap() {
const containerRef = useRef<HTMLDivElement | null>(null);
const mapRef = useRef<mapboxgl.Map | null>(null);
useEffect(() => {
if (!containerRef.current || mapRef.current) return;
let cancelled = false;
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
const map = new mapboxgl.Map({
container: containerRef.current,
style: `https://api.mappinest.com/v1/maps/light/style.json?key=${apiKey}`,
center: [0, 20],
zoom: 2
});
mapRef.current = map;
map.on('load', async () => {
try {
const response = await fetch(
`https://api.mappinest.com/v1/datasets/${datasetId}.geojson?key=${encodeURIComponent(apiKey)}`
);
if (!response.ok) throw new Error('Dataset GeoJSON request failed.');
const dataset = await response.json();
if (cancelled) return;
map.addSource('mappinest-dataset', { type: 'geojson', data: dataset });
map.addLayer({
id: 'dataset-points',
type: 'circle',
source: 'mappinest-dataset',
paint: {
'circle-color': '#2563eb',
'circle-radius': 6,
'circle-stroke-color': '#ffffff',
'circle-stroke-width': 1.5
}
});
} catch (error) {
if (!cancelled) console.error(error);
}
});
return () => {
cancelled = true;
map.remove();
mapRef.current = null;
};
}, []);
return <div ref={containerRef} style={{ height: 420, width: '100%' }} />;
}Dataset GeoJSON URL pattern
Create a browser API key in API Keys & Access, then replace YOUR_MAPPINEST_KEY. The examples use the `mappinest.world-cities` sample. Replace the Dataset ID when working with your own data.
Adjust the example center or let the map client fit the returned feature bounds when your dataset is in another location.
Refresh after publishing
Publishing in Studio or applying a server mutation creates a new immutable revision. Fetch the same endpoint URL again to receive the latest authorized revision. For explicit revalidation, store the response ETag and send it in If-None-Match. A 304 Not Modified response has no GeoJSON body, so keep the FeatureCollection already loaded by the application.
Common errors
What to read next
Last updated: September 10, 2026