About
A map maker that assumes you have data
MapCrafter turns a spreadsheet, a KML export or a boundary file into a map worth putting in front of someone. It exists because the tools that make map-making easy assume you do not have data, and the tools that handle data assume you are a cartographer.
Last updated 2026-10-22
Why it exists
The two ends of this market are well served and the middle is not. At one end, tools let you colour a pre-drawn map of a country by clicking regions — useful for a quick illustration. A list of addresses, a GPS trace or a boundary file of your own needs a different workflow. At the other end, GIS software will do anything you ask and expects you to know what to ask for.
Between them sits most of the actual work: a researcher with a CSV of survey sites, a journalist with a spreadsheet of council spending, an operations team with a list of depots and a service radius. None of them want a GIS. They want a map, and they want it to look like someone who cares made it.
That is the whole design brief. The map is the product, so the renderer and the basemaps got the attention; everything else is arranged around getting your file onto one of them.
Ten authored palettes, six OpenFreeMap choices
MapCrafter includes ten palettes authored layer by layer against the OpenMapTiles schema, plus OpenFreeMap’s Liberty, Bright, Positron, Dark, Fiord and Liberty 3D. The OpenFreeMap options use the official cartography, including its roads, labels and buildings. Choose a basemap without replacing your data or resetting the map view.
Three rules shaped them, and they are enforced by tests rather than taste:
- Water and land are never the same value. The first pass had lakes at 1.01:1 contrast against dark land, which is to say invisible. On a dark theme water has to read lighter than the land, because the land is already almost black.
- Roads carry their legibility in the casing, not the fill. A white street on cream land is only about 1.1:1 on its own. Real cartography defines it with the outline, and so does this.
- Hierarchy comes from width. A primary road and a side street share a casing colour, so colour cannot tell them apart. Stroke width does, and that is asserted by evaluating the width expressions the way the renderer does.
What it is built on
Open standards end to end, with no vendor account needed to render a map and no per-request cost to ration.
- Tiles from OpenFreeMap, which serves OpenStreetMap data in the OpenMapTiles schema. Free, no API key, no request cap.
- Rendering with MapLibre GL, the open fork of Mapbox GL. Vector tiles mean labels stay upright when the map is rotated and text stays sharp at any zoom.
- Application built with TanStack Start and Tailwind on Cloudflare Workers, with D1 and KV for projects and share links.
Imported files are parsed in your browser. Saving or publishing uploads the map document, including its layers and feature data. Address lookups send the address text to the selected geocoder.
Where the example data comes from
The gallery contains 314 worked examples and the studio offers 275 boundary datasets. Country and subdivision snapshots come from Natural Earth and US Census sources. Population and indicator examples identify their source and year on the map page. Many routes, catchments, sensor readings and grids are synthetic demonstrations built around real locations.
How correctness is enforced
A mapping tool fails quietly. Coordinates written the wrong way round put your points in the Indian Ocean, a projected coordinate system read as degrees puts them thousands of kilometres away, and both still render as a perfectly plausible map of somewhere else. There is no exception to catch.
So the invariants are asserted instead:
- Every generated style is run through MapLibre’s own validator, in every palette, option and language combination. This caught a halo property written into the wrong layer, which would have made every label on every map subtly harder to read.
- Contrast ratios between the surfaces that must be told apart are measured, not eyeballed. This is how the invisible lakes and the invisible streets were found.
- Coordinate order is asserted explicitly. GeoJSON is longitude first, and the test says so rather than relying on a map looking right.
- Import parsers report what they decided — which columns were paired, how many rows were skipped and why — so a wrong guess is visible rather than silent.
Getting in touch
Bug reports, data that would not import, and maps that came out wrong are all welcome at contact@mapcrafter.app. For import problems, describe the format and error message. Share a small, anonymised sample only if it is needed.
For what we do with your data, see the privacy policy.