HDX Humanitarian Maps


The goal of this document is to have a standard way of creating maps and avoid duplicating them and creating additional Mapbox usage for our accounts.

In the Maps section there are the main base maps to be used. These are periodically reviewed and adjusted.


Using the same base maps it will make it easier to maintain the visualisation. Base maps will automatically show the updates in all visualisations that are using it. Thus there is no effort to coordinate changes or to keep a list of usages.

We are planning to cache the most used base maps and map layers so that we can benefit from the cost savings associated in Mapbox.

There’s a small downside to using our caching layer is that I expect Mapbox might have a more extended CDN for their API.

By using the proposed base maps the visualisation will have a consistent look with the rest of the OCHA visualisations.

Whose maintaining ?

The Official UN boundaries are maintained by Paolo Palmero. When the data has issues it is updated by Paolo and 5-8 JSON files are generated. These make up the basemap with ADM0, polygons, lines, centroids, coast line and water bodies. After that the basemaps are updated automatically on the ReliefWeb Mapbox account.

Briar Mills maintains two ADM0 and ADM1 datasets with geojsons for the UN boundaries. They are hosted as a private dataset inside the HDX org.


HDX Style - HumData Account

The base map for all our future visualisations is stored under the HumData Mapbox account and is called “RW_2020-HDX” it is a copy of the base “RW_2020” that I believe Akiko was the last one to update it. Briar helped to validate the basemap and restyle the country names.

HDX Base Map - RW_2020-HDX
HDX Base Map - RW_2020-HDX

Mapbox ID: cl3lpk27k001k15msafr9714b

Preview Map: HDX Base Map

Tile Layer Cache: https://data.humdata.org/mapbox-base-tiles/{z}/{x}/{y}.png

Base Layer and Labels Layer

After some feedback sessions with Erika, we decided to stop using two separated maps (basemap and labels) because it’s not easily supported in the Mapbox GL JS and it would mean that 2 maps would have to be maintained instead of a single one.

How to build your own map?

Currently we have two ways of creating maps:

  • Leaflet

  • Mapbox

Each has its own advantages and they are widely supported.


Leaflet is the leading open-source JavaScript library for mobile-friendly interactive maps. Weighing just about 39 KB of JS, it has all the mapping features most developers ever need.

To get a feel on how to use Leaflet there is a quick-start tutorial on their website.

In order to get the base map in the current configuration, you can follow the example bellow.

First, create a map:

let map = L.map('crisis-map', { attributionControl: false });

Add the base layer:

let baseLayerUrl = `${hdxServerUrl}/mapbox-base-tiles/{z}/{x}/{y}.png`; L.tileLayer(baseLayerUrl, { attribution: '<a href="<http://www.mapbox.com/about/maps/>" target="_blank">Mapbox</a>', minZoom: 0, maxZoom: maxZoomValue }).addTo(map);

Add additional layers:

let dataLayerUrl = `...`; L.tileLayer(dataLayerUrl, { minZoom: 0, maxZoom: maxZoomValue }).addTo(map);

Similarly you can add as many additional layers with data or other functionality.


Mapbox technology originated with a team of web developers who wanted to answer this question: How can we draw a map dynamically, inside a web browser, instead of downloading static map tiles rendered on a server? They wanted to embed dynamic, interactive, customizable maps on webpages and mobile devices, and they combined vector tiles and 3D rendering technology to create a solution.

Mapbox GL JS is a client-side JavaScript library for building web maps and web applications with Mapbox's modern mapping technology. You can use Mapbox GL JS to display Mapbox maps in a web browser or client, add user interactivity, and customize the map experience in your application.

To load a style from the Mapbox API, you can use a URL of the form mapbox://styles/:owner/:style, where :owner is your Mapbox account name and :style  is the style ID.

Be sure to override mapboxgl.baseApiUrl with the value of our cache server.

If you don’t want to worry about the Token you can include the following token and the cache layer will take care of setting the correct token:

Initialise the basemap:

Other Learnings / Suggestions

Separating Map Layers from Data Layers

We need to separate the data layers belonging to the visualisation from the base map. That way we have one single base map to maintain and we have the benefit of caching the basemap both on server and on user devices / browsers.

Existing visualisations that have a basemap built in can continue to be used as they are, but for new visualisations we should try and separate the basemap from the data layers.

In Leaflet the data layers can be added as separate layers similar to how the basemap is loaded. For Mapbox GL they can be loaded as rasters, tiles or datasets. Seems there is a way to load an additional style and iterate over the layers programatically, but can’t be added to the map directly.

Render datasets directly

If we do a visualisation that we host ourselves and involves doing some coding, I suggest we should host the datasets with the points/shapes ourselves and render them directly on the map. Doing it on Mapbox seems faster and more practical if we just embed the resulting map directly somewhere.

One more benefit to rendering the points/shapes directly from the datasets would be that we would use the single source of truth for the data. For instance if I’m creating a map that has a layer country borders I could be using the dataset that stands for the base map. Same if I would do a choropleth, that also ensures that the coloured borders match with the base map.


Tilesets can be used as data layers inside a visualisation, but be sure the cache mechanism in Mapbox GL JS is active.


While developing it might be easier to use the base maps and any additional layers directly. Upon release or publishing the map / visualisation we should make sure that all urls point to the cache server and not directly to Mapbox.