You can combine OpenMapTiles with your custom vector data saved in PostGIS (there is separate article for data stored in ShapeFile or GeoJSON). Easy way is to convert your data into vector tiles and then combine it with standard OpenMapTiles source in a map style. Big advantage of this approach is that you don’t need to generate the whole OpenMapTiles schema that is quite time-consuming.

Create vector tiles from PostGIS

Setup of this solution is little bit harder then in case of data stored in ShapeFile or GeoJSON, but it gives you even better control over tiles generation plus you can use familiar SQL syntax.

Before importing the data into PostGIS

First, you need to install Docker and Docker Compose and to clone OpenMapTiles repository as described here (space and memory requirements are not so high in this case).

Add data directory as another volume of postgres service in docker-compose.yml:

    image: "openmaptiles/postgis:2.3"
    - pgdata:/var/lib/postgresql/data
    - ./data:/data

Run the database container:

docker-compose up -d postgres

Import the data into PostGIS

Move your data into data/ directory and ensure it has EPSG:3857 projection. You can use ogr2ogr for transformation:

ogr2ogr -f "ESRI ShapeFile" your_data_in_3857.shp -t_srs EPSG:3857 your_data.shp

Files inside data/ directory are visible from Docker container. Get into the postgres container:

docker-compose run --rm postgres bash

And import your data into PostgreSQL database by shp2pgsql utility:

shp2pgsql -s 3857 -I -g geometry /data/your_data_in_3857.shp your_table_name > /data/your_data.sql
PGPASSWORD=openmaptiles psql --host=postgres --port=5432 --dbname=openmaptiles --username=openmaptiles -f /data/your_data.sql | grep -v "INSERT 0 1"

Inside the container, you can run

psql postgresql://[email protected]/openmaptiles

to get into the database and check that the data was imported correctly.

Run exit to exit from container.

Configure OpenMapTiles

The next step is to configure OpenMapTiles project so that it generates tiles from your data. Basically, you need to

  • create layer definition of your data
  • change openmaptiles.yaml so that it contains only your layer(s)
  • create data/docker-compose-config.yml with zoom range and bounding box of generated tiles

Create custom layer definition

The layer definition might be the most complicated step depending on how many logic you want to implement. Very simple example consists of two files:


  id: "pubtran"
  description: |
      Links of Public Transport in Prague.
  buffer_size: 4
      description: |
          Number of the link.
      description: |
          Category of the link.
    geometry_field: geometry
    query: (SELECT geometry, custom_attribute FROM layer_pubtran(!bbox!, z(!scale_denominator!))) AS t
  - ./layer.sql


CREATE OR REPLACE FUNCTION layer_pubtran(bbox geometry, zoom_level int)
RETURNS TABLE(geometry geometry, custom_attribute text) AS $$
    SELECT geometry, custom_attribute
    FROM your_table_name
    WHERE geometry && bbox;

To better understand this example, check the documentation and inspire in definitions of OpenMapTiles layers used in production.

Change openmaptiles.yaml

Change openmaptiles.yaml so that it contains only your layer(s). It may look like:

    - layers/pubtran/pubtran.yaml
  name: OpenMapTiles
  version: 3.3.0
  id: pubtran
  description: "Sample tileset of Prague Public Transportation"
  attribution: '<a href="" target="_blank">&copy; OpenStreetMap contributors</a>'
  center: [14.403076, 50.043029, 4]
  maxzoom: 14
  minzoom: 0
    srs: +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m [email protected] +wktext +no_defs +over
      srid: 900913

You should change also at least attribution and center properties.

Create data/docker-compose-config.yml

Create data/docker-compose-config.yml with zoom range and bounding box of generated tiles:

version: "2"
      BBOX: "14.224435,49.941898,14.706787,50.177433"
      OSM_MAX_TIMESTAMP : "2017-04-19T20:14:29Z"
      OSM_AREA_NAME: "prague"
      MIN_ZOOM: "0"
      MAX_ZOOM: "14"

You can get the bounding box easily with

Generate your tiles

Run these commands to create/update other configuration files needed for generating:

docker run -v $(pwd):/tileset openmaptiles/openmaptiles-tools make clean
docker run -v $(pwd):/tileset openmaptiles/openmaptiles-tools make
docker-compose run --rm import-sql

Finally generate your tiles:

docker-compose -f docker-compose.yml -f ./data/docker-compose-config.yml  run --rm generate-vectortiles

Your MBTiles file is now at data/tiles.mbtiles. You can preview it using TileServer-GL:

docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl data/tiles.mbtiles

Data preview with TileServer-GL

Combine your vector tiles with OpenMapTiles

After creating vector tiles, you can combine it with standard OpenMapTiles layer in one map style. It can be done in the same way as in case of raster tiles.

K is an open-source project from Klokan Technologies GmbH and OSM community
Share this page on