<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[TMaps for Developers]]></title><description><![CDATA[TMaps for Developers]]></description><link>https://tmaps.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 01 Nov 2026 14:23:55 GMT</lastBuildDate><atom:link href="https://tmaps.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[MapLibre GL Vector Tiles with TMaps: Dark Mode and 3D]]></title><description><![CDATA[Vector map of Tunisia with MapLibre GL and TMaps: 4 map styles, automatic dark mode and 3D tilt. Full code and live demo.]]></description><link>https://tmaps.hashnode.dev/maplibre-gl-vector-tiles-with-tmaps-dark-mode-and-3d</link><guid isPermaLink="true">https://tmaps.hashnode.dev/maplibre-gl-vector-tiles-with-tmaps-dark-mode-and-3d</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[maps]]></category><category><![CDATA[webdev]]></category><category><![CDATA[maplibre]]></category><category><![CDATA[GIS]]></category><dc:creator><![CDATA[TMaps Teach Team]]></dc:creator><pubDate>Fri, 23 Oct 2026 15:15:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6adb7312ffec4dcf4fc0ee82/a3f09b5e-c05a-4348-b50f-7ef47eb24b39.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Raster tiles are pictures of the map. They're simple and they work everywhere, but what you get is what you get. Vector tiles send the map data itself (roads, buildings, labels) and let the browser draw it. That means the map stays sharp on any screen, zooming is smooth, you can rotate and tilt it, and you can restyle it instantly.</p>
<p>In this post we'll use <a href="https://www.tmaps.tn/en/cartes">TMaps</a> vector tiles with <a href="https://maplibre.org">MapLibre GL JS</a>, the open-source WebGL map library, and build a little style switcher with four styles.</p>
<p>Live demo: <a href="https://examples.tmaps.tn/03-vector-maplibre-styles/">examples.tmaps.tn/03-vector-maplibre-styles</a></p>
<img src="https://www.tmaps.tn/images/blog/tutoriels/maplibre-demo-page.webp" alt="MapLibre demo with the style switcher" style="display:block;margin:0 auto" />

<h2>How TMaps vector tiles work</h2>
<p>You don't request the tiles yourself. Each style is a JSON document that follows the Mapbox Style Specification:</p>
<pre><code class="language-plaintext">https://tiles.tmaps.tn/v-tile/{style}.json?api_key=YOUR_API_KEY
</code></pre>
<p>That JSON lists the tile sources, the fonts (glyphs), the icons (sprites) and how every layer should be drawn. MapLibre reads it and fetches the rest on its own. There are four styles to choose from:</p>
<table>
<thead>
<tr>
<th>Style</th>
<th>Good for</th>
</tr>
</thead>
<tbody><tr>
<td><code>streets</code></td>
<td>Everyday reference map, easy to read streets and points of interest</td>
</tr>
<tr>
<td><code>dark</code></td>
<td>Dashboards and night mode</td>
</tr>
<tr>
<td><code>terrain</code></td>
<td>Relief, rivers and topography</td>
</tr>
<tr>
<td><code>sunny</code></td>
<td>Tourism and retail, warmer colours</td>
</tr>
</tbody></table>
<h2>1. A first vector map</h2>
<p>You'll need a TMaps API key from the <a href="https://app.tmaps.tn">TMaps console</a>, with your domain (and <code>localhost</code>) in its Authorized Domains.</p>
<pre><code class="language-html">&lt;!doctype html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
  &lt;title&gt;Vector map of Tunisia&lt;/title&gt;
  &lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.6.0/dist/maplibre-gl.css"&gt;
  &lt;script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.6.0/dist/maplibre-gl.js"&gt;&lt;/script&gt;
  &lt;style&gt;
    html, body, #map { height: 100%; margin: 0; }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div id="map"&gt;&lt;/div&gt;
  &lt;script&gt;
    const API_KEY = 'YOUR_API_KEY';

    const map = new maplibregl.Map({
      container: 'map',
      style: `https://tiles.tmaps.tn/v-tile/streets.json?api_key=${API_KEY}`,
      center: [10.1815, 36.8002], // Tunis, as [lng, lat]
      zoom: 12,
      maxZoom: 18,
    });

    map.addControl(new maplibregl.NavigationControl(), 'top-right');
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>One thing to watch: MapLibre takes <code>[longitude, latitude]</code>, the opposite of Leaflet's <code>[lat, lng]</code>. Mixing them up is the most common reason a map opens in the middle of the ocean.</p>
<img src="https://www.tmaps.tn/images/blog/tutoriels/maplibre-streets.webp" alt="TMaps streets style" style="display:block;margin:0 auto" />

<h2>2. Switch styles without reloading the map</h2>
<p><code>map.setStyle(url)</code> swaps the style but keeps the map, its position and its controls. A basic switcher is only a few lines:</p>
<pre><code class="language-js">const styleUrl = (name) =&gt; `https://tiles.tmaps.tn/v-tile/${name}.json?api_key=${API_KEY}`;

for (const name of ['streets', 'dark', 'terrain', 'sunny']) {
  const button = document.createElement('button');
  button.textContent = name;
  button.addEventListener('click', () =&gt; map.setStyle(styleUrl(name)));
  document.body.append(button);
}
</code></pre>
<p>Here's the same view of Tunis in the other three styles. First <code>dark</code>, which works well on dashboards:</p>
<img src="https://www.tmaps.tn/images/blog/tutoriels/maplibre-dark.webp" alt="TMaps dark style" style="display:block;margin:0 auto" />

<p>Then <code>terrain</code>:</p>
<img src="https://www.tmaps.tn/images/blog/tutoriels/maplibre-terrain.webp" alt="TMaps terrain style" style="display:block;margin:0 auto" />

<p>And <code>sunny</code>:</p>
<img src="https://www.tmaps.tn/images/blog/tutoriels/maplibre-sunny.webp" alt="TMaps sunny style" style="display:block;margin:0 auto" />

<h3>Follow the user's dark mode</h3>
<p>Since switching is instant, you can simply follow the operating system's theme:</p>
<pre><code class="language-js">const dark = window.matchMedia('(prefers-color-scheme: dark)');
const applyTheme = () =&gt; map.setStyle(styleUrl(dark.matches ? 'dark' : 'streets'));

dark.addEventListener('change', applyTheme);
applyTheme();
</code></pre>
<h2>3. Tilt and rotate</h2>
<p>The map is drawn with WebGL, so you can tilt and rotate it, which raster tiles simply can't do:</p>
<pre><code class="language-js">map.jumpTo({
  center: [10.179, 36.799], // Medina of Tunis
  zoom: 15.5,
  pitch: 60,     // tilt, in degrees
  bearing: -25,  // rotation, in degrees
});
</code></pre>
<img src="https://www.tmaps.tn/images/blog/tutoriels/maplibre-3d-medina.webp" alt="Medina of Tunis tilted at 60 degrees" style="display:block;margin:0 auto" />

<p>Users can do the same thing themselves with a right-click drag on desktop, or two fingers on a phone.</p>
<h2>4. Customize a style</h2>
<p>The style JSON is yours to tweak. Download it, change the layers (colours, fonts, which labels show up at which zoom), and host your own copy. Just keep two things in mind:</p>
<ul>
<li>the tile URLs in <code>sources</code> must still point to <code>tiles.tmaps.tn</code> with your <code>api_key</code>, because that's how your usage is authenticated;</li>
<li>you're free to change <code>layers</code>, and also <code>glyphs</code> and <code>sprite</code> if you host your own fonts and icons.</li>
</ul>
<h2>Raster or vector?</h2>
<table>
<thead>
<tr>
<th></th>
<th>Raster</th>
<th>Vector</th>
</tr>
</thead>
<tbody><tr>
<td>Libraries</td>
<td>Leaflet, OpenLayers, any XYZ client</td>
<td>MapLibre GL JS, MapLibre Native</td>
</tr>
<tr>
<td>High-density screens</td>
<td>Blurry (no @2x yet)</td>
<td>Always sharp</td>
</tr>
<tr>
<td>Changing the style</td>
<td>Needs new tiles</td>
<td>Instant, in the browser</td>
</tr>
<tr>
<td>Rotate and tilt</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Older devices</td>
<td>Very light</td>
<td>Needs WebGL</td>
</tr>
</tbody></table>
<p>For a simple map embedded in a page, raster tiles with Leaflet are hard to beat. When the map is the heart of your product, go vector.</p>
<h2>Going further</h2>
<ul>
<li>About TMaps: <a href="https://www.tmaps.tn/en">Tunisia maps, geocoding and routing API</a></li>
<li>Live demos: <a href="https://examples.tmaps.tn">examples.tmaps.tn</a></li>
<li>Source code, MIT licensed: <a href="https://github.com/tmaps-tn/tmaps-snippets">github.com/tmaps-tn/tmaps-snippets</a></li>
<li>Postman collection: <a href="https://www.postman.com/tmaps-tn/tmaps-api">postman.com/tmaps-tn/tmaps-api</a></li>
<li>Vector tiles documentation: <a href="https://www.tmaps.tn/documentation/api/vector-tiles">tmaps.tn/documentation</a></li>
</ul>
<p>Questions or feedback? Leave a comment or write to <a href="mailto:support@tmaps.tn">support@tmaps.tn</a>.</p>
]]></content:encoded></item></channel></rss>