DEV Community

Cover image for Leaflet Tutorial: Add a Map of Tunisia with TMaps Tiles
Tmaps Tunisia
Tmaps Tunisia

Posted on

Leaflet Tutorial: Add a Map of Tunisia with TMaps Tiles

Delivery app, real estate site, store locator: sooner or later, a project in Tunisia needs a base map. And not just any map. People expect to see their neighbourhood, their street names and the road numbers they actually drive on.

In this post we'll put a map from TMaps, the maps API built for Tunisia, in Leaflet. It takes about ten lines of JavaScript. Then we'll go through the small details that tend to eat an afternoon: the API key, authorized domains, zoom limits and caching.

You can see the finished result here: examples.tmaps.tn/01-raster-leaflet

Or play with it right here, and fork it on CodePen to change the code:

Leaflet map of Greater Tunis with TMaps raster tiles

What are raster tiles?

A raster tile is a 256 × 256 PNG image showing a small square of the map. Leaflet asks for the tiles it needs to fill the screen, using the standard XYZ scheme:

https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_API_KEY
Enter fullscreen mode Exit fullscreen mode

z is the zoom level (0 to 18), and x and y are the column and row of the tile at that zoom. You never compute them yourself: you give Leaflet the template and it fills in the blanks.

1. Get an API key

  1. Create an account in the TMaps console.
  2. Create an API key. It looks like ak_ followed by 32 hexadecimal characters.
  3. In Authorized Domains, add every domain that will show the map, for example www.mysite.tn, app.mysite.tn, and localhost while you develop.

Two things that catch people out. Wildcards aren't accepted, so *.mysite.tn won't work and you have to list each subdomain. And requests must use HTTPS: plain HTTP gets a 403.

Yes, the key will be visible in your page source. That's normal for a map in the browser. The authorized domains list is what stops someone from copying it onto their own site.

2. The complete example

Save this as index.html, replace YOUR_API_KEY, and serve the folder over HTTP (npx serve . works fine):

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Map of Tunisia</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css">
  <script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"></script>
  <style>
    html, body, #map { height: 100%; margin: 0; }
  </style>
</head>
<body>
  <div id="map"></div>
  <script>
    const API_KEY = 'YOUR_API_KEY';

    const map = L.map('map').setView([36.8002, 10.1815], 12); // Tunis

    L.tileLayer(`https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=${API_KEY}`, {
      maxZoom: 18,
      attribution: '© <a href="https://www.tmaps.tn">TMaps</a>',
    }).addTo(map);
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

That's really all there is to it. Leaflet takes care of panning, zooming, touch gestures and loading tiles.

Zoom in on the Medina and you'll get down to individual streets, with names in French and Arabic:

Medina of Tunis at zoom 16 with TMaps raster tiles

3. A few details worth getting right

Set maxZoom: 18

Tiles stop at zoom 18. If you keep Leaflet's default or go higher, anyone who zooms in past 18 ends up staring at an empty grey grid. Setting maxZoom: 18 keeps the zoom buttons in line with the data.

Say something when tiles fail

With a wrong key or a domain that isn't authorized, tiles fail quietly and you just get a grey map. A one-off tileerror listener saves a lot of head scratching:

L.tileLayer(url, { maxZoom: 18 })
  .once('tileerror', () => {
    console.error('TMaps tiles could not be loaded: check your API key and its authorized domains.');
  })
  .addTo(map);
Enter fullscreen mode Exit fullscreen mode

In the network tab, a 401 means the key is missing or revoked, and a 403 means the domain isn't on the list.

Caching

Tiles come with long Cache-Control headers, so the browser keeps them between visits. On mobile, turn on your map library's disk cache and your users will thank you for the data they save.

High-density screens

There are no Retina (@2x) raster tiles yet. If the map has to stay crisp on high-density screens, or you want to change colours, rotate or tilt it, vector tiles are the better choice. That's the topic of the third post in this series.

The same tiles work everywhere

Because the URL follows the XYZ standard, you can drop it unchanged into OpenLayers, MapLibre GL, or a mobile SDK that supports XYZ layers (MapLibre Native, react-native-maps with UrlTile…). The next post does exactly that with OpenLayers, and adds a view you can share by URL (live demo).

Going further

Questions or feedback? Leave a comment below or write to support@tmaps.tn.

Top comments (0)