Maputnik: a visual editor for MapLibre GL styles
An open source visual editor for the 'MapLibre Style Specification'
At a glance
- What is it?
- Maputnik is an MIT-licensed browser editor for the MapLibre Style Specification, built in TypeScript on React and MapLibre GL JS. It is the right tool when a style JSON has outgrown hand editing, and the wrong one when you need a map server or a hosted design platform.
- Who is it for?
- Adopt Maputnik if you maintain MapLibre GL style JSON and want a visual layer for it: the browser editor at maplibre.org/maputnik keeps work in local storage, and the Docker image gives you a local server on port 8888. Skip it if what you actually need is tile hosting, a rendering backend, or a hosted design platform with accounts and sharing; Maputnik edits styles and nothing else.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Maputnik actually edits
Maputnik is a visual editor for the MapLibre Style Specification. The README describes it as "a free and open visual editor for the MapLibre GL styles targeted at developers and map designers". That sentence sets the boundary precisely: the artifact under edit is the style document, the JSON that names sources, layers, filters, paint and layout properties, and the glyph and sprite endpoints. Maputnik does not host tiles, does not render tiles on a server, and does not replace MapLibre GL JS at runtime. It is the authoring surface for the document that MapLibre GL JS later consumes.
The audience follows from that. If you write style JSON by hand in an editor and reload a browser tab to check the result, Maputnik removes the reload loop. If you are a designer who does not want to memorise the specification's property names, it gives you the property list with controls. If your styles are generated by a build script from a design token file, Maputnik is a viewer for the output, not a replacement for the generator, because the editor writes the style document directly.
How the editor is put together
The README states that Maputnik is written in TypeScript and uses React and MapLibre GL JS. The dependency list in package.json confirms the shape of that stack and adds detail: the code editor panel is built on CodeMirror packages, including @codemirror/lang-json, @codemirror/lint, @codemirror/state, @codemirror/view and a dark theme; drag and drop uses the @dnd-kit family; validation against the specification comes from @maplibre/maplibre-gl-style-spec; and two MapLibre plugins, @maplibre/maplibre-gl-geocoder and @maplibre/maplibre-gl-inspect, supply the search box and the tile inspector. The build tool is Vite, and the internationalisation setup is driven by i18next.config.ts at the repository root.
The data flow is short and worth stating plainly. A style document enters the editor, either from the built-in style list in src/config/styles.json, from a URL, or from a local file. The React application holds it in memory and renders two views of the same object: a map preview driven by MapLibre GL JS, and a form and JSON view driven by the editor components. Any change in the form is applied to the style object, and the preview re-renders. Validation from the style specification package surfaces errors in the JSON view through the CodeMirror lint extension. There is no server-side component in the editor itself, which is why the online instance can keep everything in local storage.
One structural detail is easy to miss. The repository contains a desktop/ directory, and package.json defines build-desktop, build-linux and a build-desktop script that changes the Vite mode to desktop and then invokes make inside that directory. The Dockerfile follows that path: it builds with a Go toolchain image, installs Node, npm and make, runs npm ci and then npm run build-linux, and copies the resulting binary from desktop/bin/linux into a minimal Alpine image. So the container image is not a Node server serving a static build; it is a compiled desktop binary running in a container.
Running Maputnik locally with Docker
The README gives a single Docker command for a local instance. It publishes container port 8000 on host port 8888, so the editor is reachable at http://localhost:8888.
docker run -it --rm -p 8888:8000 ghcr.io/maplibre/maputnik:mainThe same section notes that you can pass --help to see the CLI options, which cover file watching and style serving, and that you may need to mount a volume with -v to use them:
docker run -it --rm -p 8888:8000 ghcr.io/maplibre/maputnik:main --helpIf you would rather run from source, the README's develop section is the path. It requires the current active LTS Node.js version and above, and the repository pins one in .nvmrc. Install dependencies and start the dev server, then open http://localhost:8888/ in a browser.
# install dependencies
npm install
# start dev server
npm run startThe start script first copies the RTL text plugin into public/ and then runs Vite, so the first run needs node_modules populated. If you need the dev server reachable from another machine, the README points at Vite's host option:
# start externally accessible dev server
npm run start -- --host 0.0.0.0For a production bundle, npm run build runs the TypeScript compiler and then Vite in production mode. A first real use is to load an existing style, change one layer's paint property in the form panel, watch the preview update, and then export the style from the JSON view. That round trip is the whole product.
Where Maputnik stops being the right tool
Maputnik edits a style document. It does not serve the tiles that style references, and it does not give you a rendering service. If your problem is that a basemap is slow or that a source returns 404s, Maputnik will show you the broken layer in the preview but it cannot fix the upstream. The README's own framing, a visual editor for the specification, is the honest limit.
Collaboration is the second boundary. The online instance at maplibre.org/maputnik keeps work in local storage, per the README. There is no account, no shared project, no comment thread, and no server-side history. Two people editing the same style in the browser are two separate local copies. Teams that need review workflows will put the style JSON in git and use Maputnik as an editing surface whose output is committed, which is workable but is not what the editor provides on its own.
The third limit is version drift. The project has shipped v2.1.1, v3.0.0 and v3.1.0, and the version jump from 2 to 3 signals that the editor and its style specification dependency move together. If your production styles are pinned to an older specification, a newer editor may accept or normalise properties differently from your renderer. The repository does not document a compatibility matrix between editor releases and specification versions, so that check is on you.
Finally, the desktop build path is not documented in the README beyond the script names. The Dockerfile shows it compiles a Go-wrapped binary with CGO enabled, which means a C toolchain and a Go toolchain are required to reproduce it. Building the desktop binary is a heavier operation than running the web editor, and the README does not cover it.
Maputnik against hand-edited JSON and hosted design tools
The obvious alternative is editing the style JSON directly in a text editor and reloading a browser tab. The difference is not cosmetic. A text editor gives you the full document with no abstraction and no validation against the specification beyond what your editor's JSON schema plugin provides. Maputnik gives you a form view generated from the specification, so properties you did not know existed are visible, and the CodeMirror lint extension reports specification violations in the JSON pane. The cost is indirection: some edits are faster in raw JSON, particularly bulk changes across many layers, and the form view does not remove the need to understand layers and filters.
A second alternative is a hosted map design product. Those bundle style editing with tile hosting, accounts and sharing. Maputnik deliberately does not. It is a client-side editor with an MIT licence, so you can run it yourself, fork it, or embed the build behind your own infrastructure, and nothing about your style leaves the machine unless you point it at a remote source. The trade is that every surrounding piece, tile hosting, deployment, access control, is yours to assemble. For a team that already runs a tile stack, that is a smaller cost than it sounds; for a team that does not, a hosted product covers more ground out of the box.
Maintenance, releases and the MIT licence
The repository is not archived, and the last push was on 2026-09-22, days before this writing. The most recent release listed is v3.1.0 on 2026-07-06, following v3.0.0 on 2025-09-09 and v2.1.1 on 2024-08-29. That cadence matters for upgrade planning: the gap between 2.1.1 and 3.0.0 was roughly a year, and the gap between 3.0.0 and 3.1.0 was about ten months. A major version bump in that pattern is a real migration event, not a patch.
The README documents the release process in three steps. A maintainer reviews CHANGELOG.md and confirms that to-be-released changes sit under the "main" header, then runs the Create bump version PR workflow by manual dispatch with a version number input, which opens a pull request that edits the changelog and package.json. Once that pull request is merged, an automated process creates the GitHub release and uploads release assets. For a consumer, the practical consequence is that CHANGELOG.md is the authoritative place to read before upgrading, and the version in package.json tracks the release.
On licensing: Maputnik is MIT licensed, copyright Lukas Martinelli and MapLibre contributors. MIT is permissive, so the usual obligations are attribution and inclusion of the licence text, but the README adds a project-specific caution that is worth repeating rather than paraphrasing away. It asks contributors to take extra care not to violate Mapbox trademarks, and warns against getting inspired by other map studios. That is a naming and branding constraint on contributions, not a restriction on using the software. It is not legal advice; if you plan to ship a derived product under a name, read the licence and the trademark note yourself.
Editorial conclusion
Adopt Maputnik if you maintain MapLibre GL style JSON and want a visual layer for it: the browser editor at maplibre.org/maputnik keeps work in local storage, and the Docker image gives you a local server on port 8888. Skip it if what you actually need is tile hosting, a rendering backend, or a hosted design platform with accounts and sharing; Maputnik edits styles and nothing else. Before committing, verify that your style validates against the MapLibre Style Specification version Maputnik bundles, and check the CHANGELOG for the release you pin, since the project ships breaking major versions.
Frequently asked questions
How do I use Maputnik?
Open the hosted editor at https://www.maplibre.org/maputnik/, where the README says everything is stored in local storage, or run the Docker image and browse to http://localhost:8888. From there you load or create a MapLibre GL style, edit layers through the form and JSON panels, and export the result.
Can I run Maputnik locally or in Docker?
Yes. The README gives a Docker command that publishes container port 8000 on host port 8888, and a from-source path using npm install followed by npm run start, which serves the dev server on http://localhost:8888/. The README also points to the Maputnik CLI on the wiki for local style development.
Does Maputnik work with MapLibre GL JS?
It is built on it. The README states that Maputnik is written in TypeScript and uses React and MapLibre GL JS, and the package dependencies include @maplibre/maplibre-gl-style-spec for validation against the specification.
Is Maputnik free to use?
It is MIT licensed, copyright Lukas Martinelli and MapLibre contributors, and the README describes it as a free and open visual editor. The README does ask contributors to avoid violating Mapbox trademarks, which is a constraint on contributions rather than on use.
How do I run the Maputnik test suite?
End-to-end tests use Playwright from the e2e directory; the first run needs npx playwright install chromium, after which npm run test starts the dev server automatically. Unit and component tests run with npm run test-unit under Vitest.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/maplibre-maputnik)