MapLibre-Geoman vs Mapbox GL Draw: migration guide

MapLibre-Geoman and Mapbox GL Draw both support interactive geometry editing. If you are moving a Draw-based editor to Geoman, keep your GeoJSON storage model and replace the controls, mode changes and event handlers. This guide walks through that integration. For a product-level decision, see the feature and licensing comparison.
What changes when you migrate?
Mapbox GL Draw exposes a drawing control and methods such as add, getAll and changeMode. It also supports custom modes, which may be an important part of an existing application. Geoman provides a dedicated MapLibre adapter with drawing and editing modes, a feature collection API and gm:* events.
Geoman Free includes drawing, vertex editing, dragging, rotation, cutting and snapping. Tools such as splitting, scaling, measurements and auto tracing require Pro. The documentation marks Pro features with a star. Both Free and Pro applications still need their own data storage, validation and permissions.
A working MapLibre editor in Vite
This JavaScript example uses MapLibre GL JS 6 and MapLibre-Geoman Free 0.10. It uses a blank style so you can try it without a map-service token. Replace the style with your application's basemap when integrating it.
In a Vite project, install the packages:
npm install maplibre-gl@^6 @geoman-io/maplibre-geoman-free@^0.10
Add a container with an explicit height:
<div id="map" style="height: 480px"></div>
Save the following module as editor.js. The worker import is specific to Vite. For another bundler, follow the worker setup in the installation guide.
import * as ml from "maplibre-gl"
import workerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url"
import { Geoman } from "@geoman-io/maplibre-geoman-free"
import "maplibre-gl/dist/maplibre-gl.css"
import "@geoman-io/maplibre-geoman-free/dist/maplibre-geoman.css"
ml.setWorkerUrl(workerUrl)
export async function createEditor(
container,
initialData = { type: "FeatureCollection", features: [] },
) {
const map = new ml.Map({
container,
center: [0, 0],
zoom: 2,
// A blank map works without a token. Substitute your own basemap style.
style: { version: 8, sources: {}, layers: [] },
})
const geoman = new Geoman(map)
await new Promise((resolve) => geoman.mapAdapter.once("gm:loaded", resolve))
await geoman.features.importGeoJson(initialData)
return { map, geoman, getData: () => geoman.features.exportGeoJson() }
}
Create an editor from your application's entry point:
import { createEditor } from "./editor.js"
const editor = await createEditor("map")
// Or pass an existing FeatureCollection as the second argument.
await editor.geoman.enableDraw("polygon")
Click to place vertices and click the first vertex again to finish a polygon. Switch off drawing with await editor.geoman.disableDraw() and enable vertex editing with await editor.geoman.enableGlobalEditMode(). The toolbar also exposes drawing and editing modes.
Call editor.getData() from your Save action to obtain the current FeatureCollection. Send it to your own API or download it as a file. In an SSR framework, create the editor only after the container mounts. Remove the map with editor.map.remove() when the component is destroyed.
Mapbox GL Draw to Geoman API mapping
These are integration starting points, not identical signatures. Review the Draw API and Geoman API for your installed versions.
| Task | Mapbox GL Draw | MapLibre-Geoman |
|---|---|---|
| Initialize | map.addControl(new MapboxDraw()) |
new Geoman(map); wait for gm:loaded |
| Import a collection | draw.add(featureCollection) |
await geoman.features.importGeoJson(featureCollection) |
| Export current geometry | draw.getAll() |
geoman.features.exportGeoJson() |
| Start polygon drawing | draw.changeMode('draw_polygon') |
await geoman.enableDraw('polygon') |
| Edit vertices | direct_select mode with a feature ID |
Global edit mode; review selection behavior for your workflow |
| Observe creation | draw.create |
gm:create |
| Observe an edit finishing | draw.update |
gm:editend; use the operation-specific end events for dragging or rotation |
| Observe removal | draw.delete |
gm:remove |
Draw custom modes do not transfer automatically. Inventory any plugins and keyboard interactions before replacing the control. Also verify whether your own programmatic edits emit events; do not assume every library method triggers the same persistence handler.
Preserve your GeoJSON and save behavior
Start with a representative FeatureCollection from your application. Await the import before enabling editing. Check geometry types, IDs and custom properties after exporting the same collection. Drawn polygons may export as MultiPolygon geometry, so make sure your storage and validation support both Polygon and MultiPolygon. Use the import options to choose how to handle IDs and collisions, and review the export format before relying on application-specific metadata.
For automatic saving, subscribe through geoman.mapAdapter. A typical editor observes creation, removal and the completion of the editing operations it enables. Use the event reference to cover dragging, rotation or cutting in addition to vertex editing. Debounce or batch writes when a workflow produces multiple notifications. An explicit Save action can simply call editor.getData() at that moment.
Test this sequence before migrating real user data:
- Import a saved collection and verify feature counts, properties and IDs.
- Draw a polygon, move a vertex and delete a feature.
- Export, reload the result and compare the geometry with what the user saw.
- Repeat with large shapes, multi-geometries and the devices your users use.
- Check error handling and unsaved changes when the page closes or your API is unavailable.
Choose Free or Pro after testing the workflow
Start with Free if its tools cover your editor. Evaluate Pro when an integrated split, scale, measurement or auto-trace tool would replace custom implementation. Try those interactions in the MapLibre demo, which includes Pro features, and review current license and support plans.
A MapLibre/Mapbox-Geoman Pro license covers both adapters; Leaflet-Geoman Pro is licensed separately. Mapbox GL Draw itself uses the ISC license and supports commercial use under its terms. Your renderer, basemap and third-party extensions have separate licenses. The right choice depends on the workflow you can deliver and maintain.
Want more geo-editing insights?
Get tips, tutorials, and product updates delivered to your inbox.
No spam. Unsubscribe anytime.
