Shapefile(s) to vector tile set
graph LR
A[Vector source - eg. shapefile] --> |ogr2ogr| B[geoJSON]
B --> |tippecanoe| C[Set of .pbf tiles]
- Planet file mirrors: https://wiki.openstreetmap.org/wiki/Planet.osm#Planet.osm_mirrors
- Extracts: https://wiki.openstreetmap.org/wiki/Planet.osm#Planet.osm_mirrors
- Extracts (continents): https://download.geofabrik.de
Get a data source you can turn into geoJSON to use with tippecanoe (see below).
For example, convert an ABS shapefile of postcode boudnaries using ogr2ogr, which comes with GDAL (brew install gdal):
ogr2ogr -f GeoJSON postcodes.geojson POA_2021_AUST_GDA2020.shpogr2ogr doesn't reproject data into WGS 84, even though that's now the only projection supported by the geoJSON format (and what tippecanoe expects). Might wanna reproject first!
From what I understand, MapLibre used MapTiler Desktop to create the tiles, but I'm having trouble getting it to create anything. Let's try and do it ourselves.
First we create the tiles (as an .mbtiles archive) using TileMaker:
# create an .mbtiles from an osm planet file or extract (.pbf)
./tilemaker-macos-10.15/build/tilemaker \
--input tileset/australia-oceania-latest.osm.pbf \
--output aus.mbtiles \
--process ./tilemaker-macos-10.15/resources/process-openmaptiles.lua \
--config ./tilemaker-macos-10.15/resources/config-openmaptiles.jsonUse tippecanoe to turn a vector data source into a tile archive or a hierarchy of .pbf tiles
# .mbtiles output
tippecanoe -o postcodes.mbtiles postcodes.geojson
# folder of .pbf tiles output
tippecanoe --output-to-directory postcodes postcodes.geojsonSome things to note:
- Tippecanoe has a lot of options for controlling which features are visible at what zoom levels!
- In the absence of a custom name, Tippecanoe will name the layer in the tile archive after the file. Layer names are important when we start styling!
- I believe tippecanoe can combine several input files into a tile archive as separate layers. Good to know!
Use planetiler
Alternative: planetiler can also do this and is explciitly designed to ingest the whole OSM planet file if you have the RAM for it... probably more than 32 GB 😬
Tippecanoe can output either an .mbtiles archive or a folder of .pbf tiles (using the --output-to-directory option).
If we want to bundle our tiles directly with our code (eg. a JAMstack product), we can't put the tile archive directly in the project: it'll likely be bigger than the 50 MB file size limit imposed by GitHub. But we can extract the tiles into a {z}/{x}/{y).pbf directory structure and commit those to our project, provided they don't blow the total repo size.
This might be the better solution for:
- Global maps where we don't need detail beyond zoom 6 or so; or
- Regional/city maps where we don't need to zoom out much.
To extract the individual tiles .mbtiles archive (which is essentially an SQLite database), we can use Mapbox's mbutil:
mb-util aus.mbtiles aus-tiles(Apparently mb-util produces gzipped output!, but it looks like you can turn this off with a --do_compression option.)
For some maps, we may need both global overviews and regional details. In these case, we may want to put the .mbtiles archive in a remote bucket and have an edge function perform the "tile server" role, pulling out individual tiles on demand.
This isn't free in an unlimited sense the way committing tiles to version control is (at least for Cloudflare Pages), but it is potentially hundreds of tiles cheaper than a SaaS offering like Mapbox or MapTiler. It may also be useful in cases where we have a large vector dataset that we want to serve.
So your map's style.json will use a sources field to point to your new tileset:
But tippecanoe doesn't produce tiles.json, so you'll have to write it according to the Mapbox tilespec. (I've linked to version 2.0.0 here, as I'm unsure if MapLibre supports newer versions.)
(You can actually inline the tilespec in style.json!)
Mapbox's node-mbtiles has some utilities for working with .mbtiles files.
Mapbox's tippecanoe looks like it can also handle create .mbtiles files from GeoJSON features as .json files, .geobufs and potentially other input sources, so it could possible also replace the first step. It also looks quite configurable, allowing you to specify max zoom, detail, attributes, etc. It's the basis of Mapbox's Vector Tile Service, so it ought to be quite powerful.
maplibre/demotiles has free vector tiles made with MapTiler Desktop that they've released under BSD and which are already laid out in folder format, ready to be served keyless. These only go to zoom 6, so they aren't detailed enough for regional maps, but for global ones they're great and can be restyled quickly.
openmaptiles/fonts has pre-encoded versions of common open-source fonts, ready to drop into map styles.
These aren't really vector tiles, but you can do a similar thing with them: request a byte range that corresponds to a bounding box. The library's MapLibre example does this (demo here). The library handles parsing a bounding box and URL into a ranged fetch request.
PMTiles also looks like a tiled vector format designed for serverless, ranged requests. They have two MapLibre examples:
- US zip codes
- A buildings file (it says basemap, but I'm not sure if that's because it's comes from OSM)
The code on one of their demos converts a shapefile to PMTiles via .json and .mbtiles formats:
ogr2ogr -t_srs EPSG:4326 cb_2018_us_zcta510_500k.json cb_2018_us_zcta510_500k.shp
tippecanoe -zg --projection=EPSG:4326 --no-tile-compression --no-feature-limit --no-tile-size-limit -o cb_2018_us_zcta510_500k_nolimit.mbtiles -l zcta cb_2018_us_zcta510_500k.json
pmtiles-convert cb_2018_us_zcta510_500k_nolimit.mbtiles cb_2018_us_zcta510_500k_nolimit.pmtiles
Apparently PMTiles can hold arbitrary raster or vector data.
There're a few mapbox tools floating around to convert TrueType/OpenType fonts into .pbf set sby glyph (which style.json requires), but Protomaps' signed SDF tool is by far the easiest. Give it a font, it'll convert it client-side and give you a ZIP file with the .pbf set.
Tilesets get bigger exponentially with zoom. Here're the file sizes I ended up with when I converted the ABS postcodes:
| Zoom level | Size |
|---|---|
| 0 | 84K |
| 1 | 116K |
| 2 | 164K |
| 3 | 236K |
| 4 | 332K |
| 5 | 516K |
| 6 | 816K |
| 7 | 1.4M |
| 8 | 3.0M |
| 9 | 8.2M |
| 10 | 27M |
| 11 | 104M |
| 12 | 406M |
| 13 | 1.6G |
| 14 | 6.2G |
It might be worth finding a suitable max zoom for tiles like those around 10 or 11 and just overzooming!
{ # ... "sources": { "maplibre": { "url": "tiles/tiles.json", "type": "vector" } } }