<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tmaps Tunisia</title>
    <description>The latest articles on DEV Community by Tmaps Tunisia (@tmaps).</description>
    <link>https://dev.to/tmaps</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4202269%2F44391087-f85c-4be2-a89b-02896e262456.png</url>
      <title>DEV Community: Tmaps Tunisia</title>
      <link>https://dev.to/tmaps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tmaps"/>
    <language>en</language>
    <item>
      <title>TMaps API in Postman: Test Geocoding in 2 Minutes</title>
      <dc:creator>Tmaps Tunisia</dc:creator>
      <pubDate>Fri, 30 Oct 2026 09:47:39 +0000</pubDate>
      <link>https://dev.to/tmaps/tmaps-api-in-postman-test-geocoding-in-2-minutes-33oe</link>
      <guid>https://dev.to/tmaps/tmaps-api-in-postman-test-geocoding-in-2-minutes-33oe</guid>
      <description>&lt;p&gt;Before writing a single line of code against a new API, most of us want to poke at it first and see what comes back. That's what the &lt;a href="https://www.tmaps.tn/en" rel="noopener noreferrer"&gt;TMaps&lt;/a&gt; Postman collection is for: map tiles, address search, reverse geocoding and nearby places, each with documented parameters, example responses and tests.&lt;/p&gt;

&lt;p&gt;Here's how to get your first response in about two minutes, and then how to automate the whole thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://god.gw.postman.com/run-collection/59164577-39c61a9a-5dec-4a19-bfb0-78e040babbe5?action=collection%2Ffork&amp;amp;source=rip_markdown&amp;amp;collection-url=entityId%3D59164577-39c61a9a-5dec-4a19-bfb0-78e040babbe5%26entityType%3Dcollection%26workspaceId%3Dd930590d-cd34-4179-bf0c-14ef875c22af" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frun.pstmn.io%2Fbutton.svg" alt="Run in Postman" width="128" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: get a key (30 seconds)
&lt;/h2&gt;

&lt;p&gt;Create an API key in the &lt;a href="https://app.tmaps.tn" rel="noopener noreferrer"&gt;TMaps console&lt;/a&gt;. It starts with &lt;code&gt;ak_&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Postman calls the API from a server context, without an &lt;code&gt;Origin&lt;/code&gt; header, so the key's authorized domains don't come into play here. Any valid key will do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: fork the collection (30 seconds)
&lt;/h2&gt;

&lt;p&gt;Click Run in Postman above, or open the &lt;a href="https://www.postman.com/tmaps-tn/tmaps-api" rel="noopener noreferrer"&gt;public workspace&lt;/a&gt;, and choose Fork Collection. You now have your own copy of the collection in your own workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0rnry66odp41ba1ayiy3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0rnry66odp41ba1ayiy3.webp" alt="Fork the TMaps collection into your workspace" width="799" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The workspace README gives a quick overview of what's inside:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh56kq1zzw49cc35jls1z.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh56kq1zzw49cc35jls1z.webp" alt="The TMaps API public workspace" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: set your key (30 seconds)
&lt;/h2&gt;

&lt;p&gt;Open your forked collection, go to its Variables tab and add a variable called &lt;code&gt;api_key&lt;/code&gt;, with your key as the Current value. If you prefer environments, you can also fork the TMaps environment from the public workspace and set &lt;code&gt;api_key&lt;/code&gt; there.&lt;/p&gt;

&lt;p&gt;That's the only setting. The collection adds the key to every request as an &lt;code&gt;api_key&lt;/code&gt; query parameter. It's configured once in the collection's Authorization tab and every request inherits it. TMaps doesn't use an &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/p&gt;

&lt;p&gt;Keep the key in Current value: it stays on your machine and isn't shared with your workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: send your first request (30 seconds)
&lt;/h2&gt;

&lt;p&gt;Open Geocoding, then Forward geocoding, and hit Send.&lt;/p&gt;

&lt;p&gt;Each request comes with its own documentation: what it does, what it returns, and a link to the matching live demo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ub6rig3nz1sfxyzu87v.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ub6rig3nz1sfxyzu87v.webp" alt="Forward geocoding request documentation" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Params tab lists every parameter with a description. The optional ones (&lt;code&gt;proximity&lt;/code&gt;, &lt;code&gt;bbox&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;) are already there, just unchecked. Tick them to try them out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1ausnc0qxjuot2lb0p1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1ausnc0qxjuot2lb0p1.webp" alt="Documented query parameters" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the response you'll find the point in &lt;code&gt;geometry.location&lt;/code&gt;, a &lt;code&gt;formatted&lt;/code&gt; address, a &lt;code&gt;confidence&lt;/code&gt; score and the Tunisian administrative breakdown (&lt;code&gt;commune&lt;/code&gt;, &lt;code&gt;delegation&lt;/code&gt;, &lt;code&gt;governorate&lt;/code&gt;). No key yet? Open the saved example to see a real response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F60o4mnftt8yrggk3yu13.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F60o4mnftt8yrggk3yu13.webp" alt="Example response of the forward geocoding request" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Chaining requests
&lt;/h2&gt;

&lt;p&gt;The test script of Forward geocoding saves the first result's coordinates in the &lt;code&gt;lat&lt;/code&gt; and &lt;code&gt;lng&lt;/code&gt; collection variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collectionVariables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collectionVariables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lng&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So Reverse geocoding and Nearby search work straight away on the address you just found. No copying coordinates around by hand.&lt;/p&gt;

&lt;p&gt;Every request also has a few tests (status code, response shape, results sorted by distance…). After sending, you'll see them in the Tests tab of the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: run it from the command line with Newman
&lt;/h2&gt;

&lt;p&gt;The same collection runs outside Postman with &lt;a href="https://github.com/postmanlabs/newman" rel="noopener noreferrer"&gt;Newman&lt;/a&gt;. The files live in the &lt;a href="https://github.com/tmaps-tn/tmaps-snippets/tree/main/postman" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/tmaps-tn/tmaps-snippets.git
&lt;span class="nb"&gt;cd &lt;/span&gt;tmaps-snippets

npx newman run postman/TMaps-API.postman_collection.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; postman/TMaps.postman_environment.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env-var&lt;/span&gt; &lt;span class="s2"&gt;"api_key=&lt;/span&gt;&lt;span class="nv"&gt;$TMAPS_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what a run looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❏ Geocoding
↳ Forward geocoding
  GET https://api.tmaps.tn/geocoding/forward?q=Avenue Habib Bourguiba, Tunis&amp;amp;country=TN&amp;amp;limit=5&amp;amp;lang=fr&amp;amp;api_key=YOUR_API_KEY [200 OK, 3.64kB, 217ms]
  ✓  Status is 200
  ✓  Returns at least one result

↳ Reverse geocoding
  GET https://api.tmaps.tn/geocoding/reverse?lat=36.80060045491796&amp;amp;lng=10.191012134812192&amp;amp;lang=fr&amp;amp;api_key=YOUR_API_KEY [200 OK, 1.09kB, 29ms]
  ✓  Status is 200
  ✓  Returns an address

↳ Nearby search
  GET https://api.tmaps.tn/geocoding/nearby?lat=36.80060045491796&amp;amp;lng=10.191012134812192&amp;amp;radius=1000&amp;amp;categories=restaurant&amp;amp;limit=10&amp;amp;api_key=YOUR_API_KEY [200 OK, 2.38kB, 28ms]
  ✓  Status is 200
  ✓  Results are sorted by distance

│              assertions │                10 │                 0 │
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  In GitHub Actions
&lt;/h3&gt;

&lt;p&gt;Store your key as a repository secret named &lt;code&gt;TMAPS_API_KEY&lt;/code&gt;, then add a step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check the TMaps API&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;npx newman run postman/TMaps-API.postman_collection.json \&lt;/span&gt;
      &lt;span class="s"&gt;-e postman/TMaps.postman_environment.json \&lt;/span&gt;
      &lt;span class="s"&gt;--env-var "api_key=${{ secrets.TMAPS_API_KEY }}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your pipeline fails as soon as an endpoint your app relies on stops answering the way it should.&lt;/p&gt;

&lt;p&gt;One word of caution: Newman prints full request URLs, key included. Don't run it with a real key in public CI logs, or mask the output first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the collection
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Folder&lt;/th&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Maps&lt;/td&gt;
&lt;td&gt;Raster tile (PNG)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maps&lt;/td&gt;
&lt;td&gt;Vector style (MapLibre)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://tiles.tmaps.tn/v-tile/{style}.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geocoding&lt;/td&gt;
&lt;td&gt;Forward geocoding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://api.tmaps.tn/geocoding/forward&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geocoding&lt;/td&gt;
&lt;td&gt;Reverse geocoding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://api.tmaps.tn/geocoding/reverse&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geocoding&lt;/td&gt;
&lt;td&gt;Nearby search&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://api.tmaps.tn/geocoding/nearby&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Geocoding API for Tunisia: &lt;a href="https://www.tmaps.tn/en/geocoding" rel="noopener noreferrer"&gt;www.tmaps.tn/en/geocoding&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Public Postman workspace: &lt;a href="https://www.postman.com/tmaps-tn/tmaps-api" rel="noopener noreferrer"&gt;postman.com/tmaps-tn/tmaps-api&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live demos in the browser: &lt;a href="https://examples.tmaps.tn" rel="noopener noreferrer"&gt;examples.tmaps.tn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source code, MIT licensed: &lt;a href="https://github.com/tmaps-tn/tmaps-snippets" rel="noopener noreferrer"&gt;github.com/tmaps-tn/tmaps-snippets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Documentation: &lt;a href="https://www.tmaps.tn/documentation" rel="noopener noreferrer"&gt;tmaps.tn/documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions or feedback? Leave a comment or write to &lt;a href="mailto:support@tmaps.tn"&gt;support@tmaps.tn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>postman</category>
      <category>api</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Tester l'API TMaps dans Postman en 2 minutes</title>
      <dc:creator>Tmaps Tunisia</dc:creator>
      <pubDate>Fri, 30 Oct 2026 09:47:30 +0000</pubDate>
      <link>https://dev.to/tmaps/tester-lapi-tmaps-dans-postman-en-2-minutes-2np0</link>
      <guid>https://dev.to/tmaps/tester-lapi-tmaps-dans-postman-en-2-minutes-2np0</guid>
      <description>&lt;p&gt;Avant d'écrire la moindre ligne de code avec une nouvelle API, on a tous envie de la tester un peu pour voir ce qu'elle renvoie. C'est exactement le rôle de la collection Postman de &lt;a href="https://www.tmaps.tn/" rel="noopener noreferrer"&gt;TMaps&lt;/a&gt; : tuiles de carte, recherche d'adresse, géocodage inverse et lieux à proximité, chacun avec ses paramètres documentés, des exemples de réponse et des tests.&lt;/p&gt;

&lt;p&gt;Voici comment obtenir votre première réponse en deux minutes environ, puis comment automatiser le tout.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://god.gw.postman.com/run-collection/59164577-39c61a9a-5dec-4a19-bfb0-78e040babbe5?action=collection%2Ffork&amp;amp;source=rip_markdown&amp;amp;collection-url=entityId%3D59164577-39c61a9a-5dec-4a19-bfb0-78e040babbe5%26entityType%3Dcollection%26workspaceId%3Dd930590d-cd34-4179-bf0c-14ef875c22af" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frun.pstmn.io%2Fbutton.svg" alt="Run in Postman" width="128" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 1 : créer une clé (30 secondes)
&lt;/h2&gt;

&lt;p&gt;Créez une clé API sur la &lt;a href="https://app.tmaps.tn" rel="noopener noreferrer"&gt;console TMaps&lt;/a&gt;. Elle commence par &lt;code&gt;ak_&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Postman appelle l'API depuis un contexte serveur, sans en-tête &lt;code&gt;Origin&lt;/code&gt; : les domaines autorisés de la clé ne jouent donc aucun rôle ici. N'importe quelle clé valide fera l'affaire.&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 2 : copier la collection (30 secondes)
&lt;/h2&gt;

&lt;p&gt;Cliquez sur Run in Postman ci-dessus, ou ouvrez l'&lt;a href="https://www.postman.com/tmaps-tn/tmaps-api" rel="noopener noreferrer"&gt;espace de travail public&lt;/a&gt;, puis choisissez Fork Collection. Vous avez maintenant votre propre copie de la collection, dans votre espace de travail.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0rnry66odp41ba1ayiy3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0rnry66odp41ba1ayiy3.webp" alt="Copier la collection TMaps dans votre espace de travail" width="799" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le README de l'espace de travail résume ce qu'il contient :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh56kq1zzw49cc35jls1z.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh56kq1zzw49cc35jls1z.webp" alt="L'espace de travail public TMaps API" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 3 : renseigner votre clé (30 secondes)
&lt;/h2&gt;

&lt;p&gt;Ouvrez votre copie de la collection, allez dans l'onglet Variables et ajoutez une variable &lt;code&gt;api_key&lt;/code&gt;, avec votre clé comme Current value. Si vous préférez les environnements, vous pouvez aussi copier l'environnement TMaps depuis l'espace de travail public et y renseigner &lt;code&gt;api_key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;C'est le seul réglage. La collection ajoute la clé à chaque requête sous forme de paramètre &lt;code&gt;api_key&lt;/code&gt; dans l'URL. Elle est configurée une seule fois, dans l'onglet Authorization de la collection, et toutes les requêtes en héritent. TMaps n'utilise pas d'en-tête &lt;code&gt;Authorization&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Gardez bien la clé dans Current value : elle reste sur votre machine et n'est pas partagée avec votre espace de travail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 4 : envoyer votre première requête (30 secondes)
&lt;/h2&gt;

&lt;p&gt;Ouvrez Geocoding, puis Forward geocoding, et cliquez sur Send.&lt;/p&gt;

&lt;p&gt;Chaque requête a sa propre documentation : ce qu'elle fait, ce qu'elle renvoie, et un lien vers la démo en ligne correspondante.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ub6rig3nz1sfxyzu87v.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ub6rig3nz1sfxyzu87v.webp" alt="Documentation de la requête de géocodage" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L'onglet Params liste tous les paramètres avec leur description. Les paramètres facultatifs (&lt;code&gt;proximity&lt;/code&gt;, &lt;code&gt;bbox&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;) sont déjà là, simplement décochés. Cochez-les pour les essayer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1ausnc0qxjuot2lb0p1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1ausnc0qxjuot2lb0p1.webp" alt="Les paramètres documentés" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dans la réponse, vous trouverez le point dans &lt;code&gt;geometry.location&lt;/code&gt;, l'adresse complète dans &lt;code&gt;formatted&lt;/code&gt;, un score &lt;code&gt;confidence&lt;/code&gt; et le découpage administratif tunisien (&lt;code&gt;commune&lt;/code&gt;, &lt;code&gt;delegation&lt;/code&gt;, &lt;code&gt;governorate&lt;/code&gt;). Pas encore de clé ? Ouvrez l'exemple enregistré pour voir une vraie réponse :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F60o4mnftt8yrggk3yu13.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F60o4mnftt8yrggk3yu13.webp" alt="Exemple de réponse du géocodage" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enchaîner les requêtes
&lt;/h2&gt;

&lt;p&gt;Le script de test de Forward geocoding enregistre les coordonnées du premier résultat dans les variables &lt;code&gt;lat&lt;/code&gt; et &lt;code&gt;lng&lt;/code&gt; de la collection :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collectionVariables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collectionVariables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lng&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reverse geocoding et Nearby search fonctionnent donc tout de suite sur l'adresse que vous venez de trouver, sans recopier les coordonnées à la main.&lt;/p&gt;

&lt;p&gt;Chaque requête a aussi quelques tests (code de statut, forme de la réponse, résultats triés par distance…). Après l'envoi, vous les retrouvez dans l'onglet Tests de la réponse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus : lancer la collection en ligne de commande avec Newman
&lt;/h2&gt;

&lt;p&gt;La même collection fonctionne en dehors de Postman grâce à &lt;a href="https://github.com/postmanlabs/newman" rel="noopener noreferrer"&gt;Newman&lt;/a&gt;. Les fichiers sont dans le &lt;a href="https://github.com/tmaps-tn/tmaps-snippets/tree/main/postman" rel="noopener noreferrer"&gt;dépôt GitHub&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/tmaps-tn/tmaps-snippets.git
&lt;span class="nb"&gt;cd &lt;/span&gt;tmaps-snippets

npx newman run postman/TMaps-API.postman_collection.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; postman/TMaps.postman_environment.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env-var&lt;/span&gt; &lt;span class="s2"&gt;"api_key=&lt;/span&gt;&lt;span class="nv"&gt;$TMAPS_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voici à quoi ressemble une exécution :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❏ Geocoding
↳ Forward geocoding
  GET https://api.tmaps.tn/geocoding/forward?q=Avenue Habib Bourguiba, Tunis&amp;amp;country=TN&amp;amp;limit=5&amp;amp;lang=fr&amp;amp;api_key=VOTRE_CLE_API [200 OK, 3.64kB, 217ms]
  ✓  Status is 200
  ✓  Returns at least one result

↳ Reverse geocoding
  GET https://api.tmaps.tn/geocoding/reverse?lat=36.80060045491796&amp;amp;lng=10.191012134812192&amp;amp;lang=fr&amp;amp;api_key=VOTRE_CLE_API [200 OK, 1.09kB, 29ms]
  ✓  Status is 200
  ✓  Returns an address

↳ Nearby search
  GET https://api.tmaps.tn/geocoding/nearby?lat=36.80060045491796&amp;amp;lng=10.191012134812192&amp;amp;radius=1000&amp;amp;categories=restaurant&amp;amp;limit=10&amp;amp;api_key=VOTRE_CLE_API [200 OK, 2.38kB, 28ms]
  ✓  Status is 200
  ✓  Results are sorted by distance

│              assertions │                10 │                 0 │
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dans GitHub Actions
&lt;/h3&gt;

&lt;p&gt;Enregistrez votre clé comme secret du dépôt sous le nom &lt;code&gt;TMAPS_API_KEY&lt;/code&gt;, puis ajoutez une étape :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check the TMaps API&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;npx newman run postman/TMaps-API.postman_collection.json \&lt;/span&gt;
      &lt;span class="s"&gt;-e postman/TMaps.postman_environment.json \&lt;/span&gt;
      &lt;span class="s"&gt;--env-var "api_key=${{ secrets.TMAPS_API_KEY }}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Votre pipeline échoue désormais dès qu'un endpoint dont votre application dépend ne répond plus comme prévu.&lt;/p&gt;

&lt;p&gt;Petite mise en garde : Newman affiche les URL complètes des requêtes, clé comprise. Ne l'utilisez pas avec une vraie clé dans des logs de CI publics, ou masquez la sortie avant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ce que contient la collection
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dossier&lt;/th&gt;
&lt;th&gt;Requête&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Maps&lt;/td&gt;
&lt;td&gt;Raster tile (PNG)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maps&lt;/td&gt;
&lt;td&gt;Vector style (MapLibre)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://tiles.tmaps.tn/v-tile/{style}.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geocoding&lt;/td&gt;
&lt;td&gt;Forward geocoding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://api.tmaps.tn/geocoding/forward&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geocoding&lt;/td&gt;
&lt;td&gt;Reverse geocoding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://api.tmaps.tn/geocoding/reverse&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geocoding&lt;/td&gt;
&lt;td&gt;Nearby search&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET https://api.tmaps.tn/geocoding/nearby&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Pour aller plus loin
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;L'API de géocodage pour la Tunisie : &lt;a href="https://www.tmaps.tn/geocoding" rel="noopener noreferrer"&gt;www.tmaps.tn/geocoding&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;L'espace de travail Postman public : &lt;a href="https://www.postman.com/tmaps-tn/tmaps-api" rel="noopener noreferrer"&gt;postman.com/tmaps-tn/tmaps-api&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Les démos dans le navigateur : &lt;a href="https://examples.tmaps.tn" rel="noopener noreferrer"&gt;examples.tmaps.tn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Le code source, sous licence MIT : &lt;a href="https://github.com/tmaps-tn/tmaps-snippets" rel="noopener noreferrer"&gt;github.com/tmaps-tn/tmaps-snippets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;La documentation : &lt;a href="https://www.tmaps.tn/documentation" rel="noopener noreferrer"&gt;tmaps.tn/documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une question ou une remarque ? Laissez un commentaire ou écrivez-nous à &lt;a href="mailto:support@tmaps.tn"&gt;support@tmaps.tn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>postman</category>
      <category>api</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Google Maps Alternative for Tunisia: TMaps Compared</title>
      <dc:creator>Tmaps Tunisia</dc:creator>
      <pubDate>Mon, 26 Oct 2026 13:42:17 +0000</pubDate>
      <link>https://dev.to/tmaps/google-maps-alternative-for-tunisia-tmaps-compared-3aoa</link>
      <guid>https://dev.to/tmaps/google-maps-alternative-for-tunisia-tmaps-compared-3aoa</guid>
      <description>&lt;p&gt;If you build an app for the Tunisian market, Google Maps is the default choice. Everyone knows it, it covers everything, and you've probably used it before. Then the first invoice arrives, in US dollars, charged to an international card, and you start wondering whether there's an alternative built for Tunisia.&lt;/p&gt;

&lt;p&gt;We built &lt;a href="https://www.tmaps.tn/en/google-maps-alternative" rel="noopener noreferrer"&gt;TMaps&lt;/a&gt; to answer that question. But instead of a sales pitch, this post compares the two the way a developer would: the code, the billing model, real prices on three scenarios, and the cases where Google is still the better pick.&lt;/p&gt;

&lt;p&gt;We'll stick to the two most common needs: &lt;strong&gt;showing a map&lt;/strong&gt; and &lt;strong&gt;finding an address&lt;/strong&gt; (geocoding). Routing deserves its own comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The code: what does a migration look like?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Showing a map
&lt;/h3&gt;

&lt;p&gt;With Google Maps, you load Google's JavaScript SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"map"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height: 400px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.1815&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// Tunis&lt;/span&gt;
      &lt;span class="na"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_KEY&amp;amp;callback=initMap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With TMaps, you pick an open-source library (Leaflet here) and point it at the TMaps tiles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"map"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height: 400px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setView&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.1815&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Tunis&lt;/span&gt;
  &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tileLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_TMAPS_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;maxZoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;© TMaps&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;addTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real difference isn't the line count. With Google, your code depends on Google's SDK. With TMaps, it depends on Leaflet, OpenLayers or MapLibre, which are open source: if you ever switch tile providers, you don't rewrite your map, you change a URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding an address
&lt;/h3&gt;

&lt;p&gt;On the Google side, you call the Geocoding API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://maps.googleapis.com/maps/api/geocode/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rue de Marseille, Tunis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GOOGLE_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the TMaps side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.tmaps.tn/geocoding/forward&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rue de Marseille, Tunis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TMAPS_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good news if you're migrating: the coordinates live in the same place, &lt;code&gt;geometry.location&lt;/code&gt;. Where they really differ is the address breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google returns a generic &lt;code&gt;address_components&lt;/code&gt; array where each item has &lt;code&gt;types&lt;/code&gt; (&lt;code&gt;locality&lt;/code&gt;, &lt;code&gt;administrative_area_level_1&lt;/code&gt;…). Mapping those types to Tunisian administrative levels is up to you.&lt;/li&gt;
&lt;li&gt;TMaps returns fields named after the Tunisian administrative structure:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"street"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rue de Marseille"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"commune"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Habib Thameur"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"delegation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bab El Bhar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"governorate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tunis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TN"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your delivery form asks for the delegation and the governorate, that's mapping code you don't have to write.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Billing: two different units
&lt;/h2&gt;

&lt;p&gt;This is the part you really need to understand before comparing prices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google&lt;/strong&gt; bills a map &lt;strong&gt;per load&lt;/strong&gt;: when a page displays the map, that's one billable event, no matter how many tiles it loads afterwards. Geocoding is billed per request. Each product has a monthly free cap: 10,000 map loads and 10,000 geocoding requests. Beyond that, you pay per thousand, in US dollars.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TMaps&lt;/strong&gt; counts every &lt;strong&gt;successful request&lt;/strong&gt; as one call: a map tile or a geocoding request. Plans are monthly bundles priced in Tunisian dinars (TND), with a number of calls included. Past your quota, every extra 1,000 calls costs 0.5 TND, and the service is never cut off. The Free plan includes 50,000 calls a month, commercial use included.&lt;/p&gt;

&lt;p&gt;So a TMaps map uses &lt;strong&gt;several calls per display&lt;/strong&gt;. We measured it on our demos, with a 1500 × 963 pixel map:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;with raster tiles (Leaflet), the first display loads &lt;strong&gt;35 tiles&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;with vector tiles (MapLibre), it loads &lt;strong&gt;12&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tiles already in the browser cache aren't requested again, but to stay on the safe side, we count every display as a first visit.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Prices on three scenarios
&lt;/h2&gt;

&lt;p&gt;Sources: the &lt;a href="https://developers.google.com/maps/billing-and-pricing/pricing" rel="noopener noreferrer"&gt;Google Maps Platform price list&lt;/a&gt; (updated October 21, 2026) and the &lt;a href="https://www.tmaps.tn/en/pricing" rel="noopener noreferrer"&gt;TMaps pricing page&lt;/a&gt;. To compare, we use about 3 TND per US dollar (Central Bank of Tunisia rate on October 8, 2026). Google prices exclude taxes and international payment fees.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 1: a small showcase site
&lt;/h3&gt;

&lt;p&gt;3,000 map displays and 1,000 address searches per month, commercial use.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google: $0.&lt;/strong&gt; Everything fits in the free caps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TMaps: 0 TND&lt;/strong&gt; (Free plan, commercial use allowed). With vector tiles, 3,000 displays × 12 tiles + 1,000 geocoding requests is about 37,000 calls, under the plan's 50,000.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A tie, then. The difference shows up as traffic grows: the TMaps Free plan covers about 4,000 vector map displays a month (or 1,400 with raster tiles), while Google stays free up to 10,000 map loads. In between, Google costs nothing and TMaps moves to the Starter plan at 79 TND a month. No point pretending otherwise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 2: a delivery app
&lt;/h3&gt;

&lt;p&gt;200,000 geocoding requests per month (entering and checking customer addresses), not much map display.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google: $850/month, about 2,550 TND.&lt;/strong&gt; The first 10,000 are free, then 90,000 at $5 per thousand and 100,000 at $4 per thousand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TMaps: 79 TND/month&lt;/strong&gt; (Starter plan, 200,000 calls included).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where the gap is widest: geocoding is a big line item on a Google invoice, and it's part of the bundle with TMaps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 3: an e-commerce site
&lt;/h3&gt;

&lt;p&gt;30,000 map displays and 20,000 address searches per month.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google: $190/month, about 570 TND.&lt;/strong&gt; 20,000 paid map loads at $7 per thousand, plus 10,000 paid geocoding requests at $5 per thousand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TMaps with vector tiles (MapLibre): 229 TND/month&lt;/strong&gt; (Growth plan). 30,000 × 12 tiles + 20,000 geocoding requests is about 380,000 calls, under the plan's 750,000.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TMaps with raster tiles (Leaflet): 599 TND/month&lt;/strong&gt; (Business plan). At 35 tiles per display, you reach about 1,070,000 calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This one shows how much the technical choice matters: with vector tiles, TMaps costs about 2.5 times less than Google; with raster tiles, it ends up slightly more expensive. If your site shows a lot of maps, go vector.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Google&lt;/th&gt;
&lt;th&gt;TMaps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Small showcase site (3,000 maps a month)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;0 TND&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mid-size site (8,000 maps a month)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;79 TND&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivery app&lt;/td&gt;
&lt;td&gt;≈ 2,550 TND ($850)&lt;/td&gt;
&lt;td&gt;79 TND&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce, vector maps&lt;/td&gt;
&lt;td&gt;≈ 570 TND ($190)&lt;/td&gt;
&lt;td&gt;229 TND&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce, raster maps&lt;/td&gt;
&lt;td&gt;≈ 570 TND ($190)&lt;/td&gt;
&lt;td&gt;599 TND&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. What the price list doesn't show
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The street reference.&lt;/strong&gt; This is probably the biggest difference, and no price list shows it. The TMaps database holds more than 120,000 roads, with a verified name for 72% of road segments on average. According to our coverage measurement, published and recomputed every week on the &lt;a href="https://www.tmaps.tn/couverture-cartographique" rel="noopener noreferrer"&gt;map coverage page&lt;/a&gt; (in French), TMaps shows on average &lt;strong&gt;twice as many named roads as Google Maps&lt;/strong&gt; across Tunisia's 24 governorates, especially in suburban areas and new neighbourhoods. Streets are named in French and Arabic, including the informal local names people actually use.&lt;/p&gt;

&lt;p&gt;For a delivery app, that's very concrete: a street with no name is an address your customer can't type, and a driver who has to call to ask for directions. This is our own measurement, not an independent audit, so check it on your area: the side-by-side pages show Google on the left and TMaps on the right, for example in &lt;a href="https://www.tmaps.tn/en/comparez-vous-meme/ben-arous" rel="noopener noreferrer"&gt;Ben Arous&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Currency.&lt;/strong&gt; Google bills in US dollars, through a billing account and an international payment method, so every move of the dinar changes your invoice. TMaps bills in dinars, with no exchange-rate exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overages.&lt;/strong&gt; With TMaps, a traffic spike never takes the service down: it's billed at the overage rate on the next invoice. With Google, pay-as-you-go has no ceiling by default, so set quotas and budget alerts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arabic and Arabizi.&lt;/strong&gt; Tunisian addresses get typed in French, in Arabic script and in Arabizi (&lt;code&gt;nahj&lt;/code&gt;, &lt;code&gt;9asr said&lt;/code&gt;). Another post in this series shows how to build an address search that handles all three, and you can try it in the &lt;a href="https://examples.tmaps.tn/04-geocoding-search/" rel="noopener noreferrer"&gt;address search demo&lt;/a&gt;: type &lt;code&gt;9asr said&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support.&lt;/strong&gt; A team based in Tunis, working Tunisian hours, on one side; the support desk of a global platform on the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. When to stay on Google Maps
&lt;/h2&gt;

&lt;p&gt;An honest comparison also has to say when not to switch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your traffic fits in Google's free caps but not in the TMaps Free plan&lt;/strong&gt; (roughly 4,000 to 10,000 maps a month): with Google, you won't pay anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your app covers several countries&lt;/strong&gt;, and Tunisia is just one market among others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You rely on services TMaps doesn't offer&lt;/strong&gt;: Street View, Google's global places database with reviews and photos, or mobile SDKs your team already knows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, TMaps makes sense when Tunisia is your main market, when your customers live in new or suburban neighbourhoods where named streets make the difference, when you geocode a lot of addresses, when you want a fixed invoice in dinars, or when you'd rather build your map on open-source libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  See for yourself
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Compare both maps in &lt;a href="https://www.tmaps.tn/en/comparez-vous-meme/ben-arous" rel="noopener noreferrer"&gt;Ben Arous&lt;/a&gt;, &lt;a href="https://www.tmaps.tn/en/comparez-vous-meme/sfax" rel="noopener noreferrer"&gt;Sfax&lt;/a&gt; or &lt;a href="https://www.tmaps.tn/en/comparez-vous-meme/nabeul" rel="noopener noreferrer"&gt;Nabeul&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Road coverage, governorate by governorate: &lt;a href="https://www.tmaps.tn/couverture-cartographique" rel="noopener noreferrer"&gt;map coverage&lt;/a&gt; (in French)&lt;/li&gt;
&lt;li&gt;Try the API without writing code in the &lt;a href="https://www.postman.com/tmaps-tn/tmaps-api" rel="noopener noreferrer"&gt;Postman collection&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live demos and their code: &lt;a href="https://examples.tmaps.tn" rel="noopener noreferrer"&gt;examples.tmaps.tn&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prices quoted here are from October 2026 and can change: always check the official price lists before you decide. Questions about a migration? Leave a comment or write to &lt;a href="mailto:support@tmaps.tn"&gt;support@tmaps.tn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>googlemaps</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Migrer de Google Maps vers TMaps en Tunisie</title>
      <dc:creator>Tmaps Tunisia</dc:creator>
      <pubDate>Mon, 26 Oct 2026 10:33:40 +0000</pubDate>
      <link>https://dev.to/tmaps/migrer-de-google-maps-vers-tmaps-en-tunisie-2i51</link>
      <guid>https://dev.to/tmaps/migrer-de-google-maps-vers-tmaps-en-tunisie-2i51</guid>
      <description>&lt;p&gt;Vous avez une application tunisienne qui tourne sur Google Maps et vous envisagez de passer à &lt;a href="https://www.tmaps.tn/google-maps-alternative" rel="noopener noreferrer"&gt;TMaps&lt;/a&gt;. Bonne nouvelle : pour les deux usages les plus courants, afficher une carte et transformer une adresse en coordonnées, la migration tient en quelques fichiers. Cet article passe en revue ce qui change dans le code, ce qui ne change pas, et le piège de facturation à connaître avant de mettre en production.&lt;/p&gt;

&lt;p&gt;Ce guide ne parle pas d'itinéraires : on se limite à la carte et au géocodage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 1 : remplacer le SDK Google par Leaflet
&lt;/h2&gt;

&lt;p&gt;Côté Google, une carte typique ressemble à ceci :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"map"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height: 400px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.1815&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Marker&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.1815&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://maps.googleapis.com/maps/api/js?key=VOTRE_CLE_GOOGLE&amp;amp;callback=initMap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TMaps ne fournit pas de SDK propriétaire. On garde une bibliothèque open source et on lui donne l'URL des tuiles TMaps. Avec Leaflet, l'équivalent s'écrit :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"map"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height: 400px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setView&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.1815&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tileLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=VOTRE_CLE_TMAPS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;maxZoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;© TMaps&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;addTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.1815&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;addTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quelques correspondances utiles pendant la réécriture :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Google Maps JS&lt;/th&gt;
&lt;th&gt;Leaflet&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;new google.maps.Map(el, { center, zoom })&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;L.map(el).setView([lat, lng], zoom)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;new google.maps.Marker({ position, map })&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;L.marker([lat, lng]).addTo(map)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{ lat: 36.8, lng: 10.18 }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[36.8, 10.18]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;chargement asynchrone et &lt;code&gt;callback=initMap&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;script classique, la carte existe tout de suite&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plus de callback global, plus de clé Google dans le HTML. Et surtout, votre code ne dépend plus d'un fournisseur : changer de source de tuiles un jour reviendra à modifier une URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54w5rhqi0hhxekgyyayz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54w5rhqi0hhxekgyyayz.webp" alt="Carte Leaflet de Tunis avec les tuiles TMaps" width="799" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 2 : passer au vectoriel (vraiment)
&lt;/h2&gt;

&lt;p&gt;Le raster avec Leaflet est la façon la plus directe de remplacer Google, mais ce n'est pas celle que nous conseillons pour la production. Avec MapLibre GL JS et les tuiles vectorielles, la migration reste aussi courte :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;maplibregl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://tiles.tmaps.tn/v-tile/streets.json?api_key=VOTRE_CLE_TMAPS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;10.1815&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// attention : [lng, lat]&lt;/span&gt;
  &lt;span class="na"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;maplibregl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Marker&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setLngLat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;10.1815&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;addTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Piège classique en venant de Google : MapLibre attend &lt;code&gt;[longitude, latitude]&lt;/code&gt;. Si votre carte s'ouvre au milieu de l'océan, c'est presque toujours ça.&lt;/p&gt;

&lt;p&gt;La raison de ce conseil tient à la facturation, détaillée plus bas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 3 : migrer le géocodage
&lt;/h2&gt;

&lt;p&gt;Ici, le changement est minime. Avant :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://maps.googleapis.com/maps/api/geocode/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rue de Marseille, Tunis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GOOGLE_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Après :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.tmaps.tn/geocoding/forward&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rue de Marseille, Tunis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TMAPS_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quatre paramètres renommés (&lt;code&gt;address&lt;/code&gt; devient &lt;code&gt;q&lt;/code&gt;, &lt;code&gt;region&lt;/code&gt; devient &lt;code&gt;country&lt;/code&gt;, &lt;code&gt;language&lt;/code&gt; devient &lt;code&gt;lang&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt; devient &lt;code&gt;api_key&lt;/code&gt;) et c'est tout. La dernière ligne est strictement identique : les coordonnées sont dans &lt;code&gt;geometry.location&lt;/code&gt;, comme chez Google. Le code qui place un marqueur ou enregistre une position en base n'a pas à bouger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Étape 4 : simplifier le découpage de l'adresse
&lt;/h2&gt;

&lt;p&gt;C'est là que la migration fait gagner du code. Chez Google, l'adresse détaillée arrive sous forme de tableau générique &lt;code&gt;address_components&lt;/code&gt;, et il faut aller chercher chaque niveau par son type :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;address_components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;))?.&lt;/span&gt;&lt;span class="nx"&gt;long_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;governorate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;administrative_area_level_1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;locality&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// et la délégation ? À vérifier au cas par cas selon l'adresse...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ce code de correspondance est fragile : les types génériques ne collent pas toujours aux niveaux administratifs tunisiens, et on finit avec des cas particuliers. TMaps renvoie directement des champs nommés selon le découpage du pays :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"street"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rue de Marseille"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"commune"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Habib Thameur"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"delegation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bab El Bhar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"governorate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tunis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TN"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La fonction &lt;code&gt;pick&lt;/code&gt; disparaît :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;commune&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delegation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;governorate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pour un formulaire de livraison qui calcule ses frais par délégation, c'est une source de bugs en moins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le piège : l'unité de facturation n'est pas la même
&lt;/h2&gt;

&lt;p&gt;Avant de comparer des factures, il faut comprendre ce qu'on compte.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google&lt;/strong&gt; facture la carte &lt;strong&gt;au chargement&lt;/strong&gt; : une page qui affiche une carte compte pour un, quel que soit le nombre de tuiles téléchargées ensuite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TMaps&lt;/strong&gt; compte &lt;strong&gt;chaque requête réussie&lt;/strong&gt; : une tuile, c'est un appel ; un géocodage, c'est un appel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une carte TMaps consomme donc plusieurs appels par affichage. Mesuré sur nos démos avec une carte de 1500 × 963 pixels, le premier affichage charge environ &lt;strong&gt;35 tuiles en raster&lt;/strong&gt; (Leaflet) contre &lt;strong&gt;12 en vectoriel&lt;/strong&gt; (MapLibre). Les tuiles déjà en cache dans le navigateur ne sont pas redemandées, mais pour estimer votre consommation, comptez chaque affichage comme une première visite.&lt;/p&gt;

&lt;p&gt;D'où le conseil de l'étape 2 : à trafic égal, le vectoriel divise à peu près par trois le nombre d'appels liés à la carte. Si vous migrez une application qui affiche beaucoup de cartes, c'est le réglage qui pèse le plus sur la facture. Le géocodage, lui, reste à un appel par requête dans les deux cas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Et les prix ?
&lt;/h2&gt;

&lt;p&gt;On ne refait pas le calcul ici. Nous avons publié un &lt;a href="https://www.tmaps.tn/blog/alternative-google-maps-tunisie-comparatif" rel="noopener noreferrer"&gt;comparatif complet de Google Maps et TMaps&lt;/a&gt; avec les prix en dinars sur plusieurs scénarios (petite vitrine, livraison, e-commerce), le référentiel des rues, et les cas où il vaut mieux rester sur Google. Les grilles de TMaps sont sur la page &lt;a href="https://www.tmaps.tn/pricing" rel="noopener noreferrer"&gt;tarifs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Avant de migrer, regardez aussi la carte elle-même sur votre zone : les pages « Comparez vous-même » affichent Google et TMaps côte à côte, par exemple sur &lt;a href="https://www.tmaps.tn/comparez-vous-meme/ben-arous" rel="noopener noreferrer"&gt;Ben Arous&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist de migration
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Remplacer le script Google par Leaflet, ou mieux, MapLibre avec les tuiles vectorielles.&lt;/li&gt;
&lt;li&gt;Inverser l'ordre des coordonnées si vous passez à MapLibre (&lt;code&gt;[lng, lat]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Renommer les paramètres du géocodage, garder la lecture de &lt;code&gt;geometry.location&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Supprimer le code de correspondance des &lt;code&gt;address_components&lt;/code&gt; au profit de &lt;code&gt;components&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Estimer la consommation en tuiles par affichage, pas en chargements de carte.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les démos et leur code sont sur &lt;a href="https://examples.tmaps.tn" rel="noopener noreferrer"&gt;examples.tmaps.tn&lt;/a&gt;, et le dépôt &lt;a href="https://github.com/tmaps-tn/tmaps-snippets" rel="noopener noreferrer"&gt;tmaps-snippets&lt;/a&gt; contient les exemples de cette série. Une question sur votre migration ? Laissez un commentaire ou écrivez-nous à &lt;a href="mailto:support@tmaps.tn"&gt;support@tmaps.tn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>googlemaps</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>MapLibre GL Vector Tiles with TMaps: Dark Mode and 3D</title>
      <dc:creator>Tmaps Tunisia</dc:creator>
      <pubDate>Fri, 23 Oct 2026 13:28:05 +0000</pubDate>
      <link>https://dev.to/tmaps/vector-maps-of-tunisia-with-maplibre-gl-4-styles-dark-mode-and-3d-tilt-59l1</link>
      <guid>https://dev.to/tmaps/vector-maps-of-tunisia-with-maplibre-gl-4-styles-dark-mode-and-3d-tilt-59l1</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;In this post we'll use &lt;a href="https://www.tmaps.tn/en/cartes" rel="noopener noreferrer"&gt;TMaps&lt;/a&gt; vector tiles with &lt;a href="https://maplibre.org" rel="noopener noreferrer"&gt;MapLibre GL JS&lt;/a&gt;, the open-source WebGL map library, and build a little style switcher with four styles.&lt;/p&gt;

&lt;p&gt;Live demo: &lt;a href="https://examples.tmaps.tn/03-vector-maplibre-styles/" rel="noopener noreferrer"&gt;examples.tmaps.tn/03-vector-maplibre-styles&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk9w89jtskw8fti6myz14.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk9w89jtskw8fti6myz14.webp" alt="MapLibre demo with the style switcher" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How TMaps vector tiles work
&lt;/h2&gt;

&lt;p&gt;You don't request the tiles yourself. Each style is a JSON document that follows the Mapbox Style Specification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://tiles.tmaps.tn/v-tile/{style}.json?api_key=YOUR_API_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Style&lt;/th&gt;
&lt;th&gt;Good for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;streets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Everyday reference map, easy to read streets and points of interest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dark&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dashboards and night mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terrain&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Relief, rivers and topography&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sunny&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tourism and retail, warmer colours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. A first vector map
&lt;/h2&gt;

&lt;p&gt;You'll need a TMaps API key from the &lt;a href="https://app.tmaps.tn" rel="noopener noreferrer"&gt;TMaps console&lt;/a&gt;, with your domain (and &lt;code&gt;localhost&lt;/code&gt;) in its Authorized Domains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Vector map of Tunisia&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/maplibre-gl@5.6.0/dist/maplibre-gl.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/maplibre-gl@5.6.0/dist/maplibre-gl.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;#map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"map"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;maplibregl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://tiles.tmaps.tn/v-tile/streets.json?api_key=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;10.1815&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;36.8002&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Tunis, as [lng, lat]&lt;/span&gt;
      &lt;span class="na"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;maxZoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;maplibregl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NavigationControl&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top-right&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing to watch: MapLibre takes &lt;code&gt;[longitude, latitude]&lt;/code&gt;, the opposite of Leaflet's &lt;code&gt;[lat, lng]&lt;/code&gt;. Mixing them up is the most common reason a map opens in the middle of the ocean.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7q825hom30o3vyoqjqlz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7q825hom30o3vyoqjqlz.webp" alt="TMaps streets style" width="799" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Switch styles without reloading the map
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;map.setStyle(url)&lt;/code&gt; swaps the style but keeps the map, its position and its controls. A basic switcher is only a few lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styleUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`https://tiles.tmaps.tn/v-tile/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json?api_key=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;streets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;terrain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sunny&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;styleUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the same view of Tunis in the other three styles. First &lt;code&gt;dark&lt;/code&gt;, which works well on dashboards:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F26wk8dw9gpk6abg3ajmc.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F26wk8dw9gpk6abg3ajmc.webp" alt="TMaps dark style" width="799" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;terrain&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fti9d3x2v6g3ttouctq2i.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fti9d3x2v6g3ttouctq2i.webp" alt="TMaps terrain style" width="799" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;sunny&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0q4ggt2h6vlz7sm4j4z8.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0q4ggt2h6vlz7sm4j4z8.webp" alt="TMaps sunny style" width="799" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow the user's dark mode
&lt;/h3&gt;

&lt;p&gt;Since switching is instant, you can simply follow the operating system's theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-color-scheme: dark)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;applyTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;styleUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;streets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;applyTheme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;applyTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Tilt and rotate
&lt;/h2&gt;

&lt;p&gt;The map is drawn with WebGL, so you can tilt and rotate it, which raster tiles simply can't do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jumpTo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;10.179&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;36.799&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Medina of Tunis&lt;/span&gt;
  &lt;span class="na"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;15.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pitch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// tilt, in degrees&lt;/span&gt;
  &lt;span class="na"&gt;bearing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// rotation, in degrees&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3w5yaffjyevkludi51x.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3w5yaffjyevkludi51x.webp" alt="Medina of Tunis tilted at 60 degrees" width="799" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Users can do the same thing themselves with a right-click drag on desktop, or two fingers on a phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Customize a style
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the tile URLs in &lt;code&gt;sources&lt;/code&gt; must still point to &lt;code&gt;tiles.tmaps.tn&lt;/code&gt; with your &lt;code&gt;api_key&lt;/code&gt;, because that's how your usage is authenticated;&lt;/li&gt;
&lt;li&gt;you're free to change &lt;code&gt;layers&lt;/code&gt;, and also &lt;code&gt;glyphs&lt;/code&gt; and &lt;code&gt;sprite&lt;/code&gt; if you host your own fonts and icons.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Raster or vector?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Raster&lt;/th&gt;
&lt;th&gt;Vector&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Libraries&lt;/td&gt;
&lt;td&gt;Leaflet, OpenLayers, any XYZ client&lt;/td&gt;
&lt;td&gt;MapLibre GL JS, MapLibre Native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High-density screens&lt;/td&gt;
&lt;td&gt;Blurry (no @2x yet)&lt;/td&gt;
&lt;td&gt;Always sharp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changing the style&lt;/td&gt;
&lt;td&gt;Needs new tiles&lt;/td&gt;
&lt;td&gt;Instant, in the browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rotate and tilt&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Older devices&lt;/td&gt;
&lt;td&gt;Very light&lt;/td&gt;
&lt;td&gt;Needs WebGL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a simple map embedded in a page, raster tiles with Leaflet are hard to beat (that's the first post of this series). When the map is the heart of your product, go vector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;About TMaps: &lt;a href="https://www.tmaps.tn/en" rel="noopener noreferrer"&gt;Tunisia maps, geocoding and routing API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live demos: &lt;a href="https://examples.tmaps.tn" rel="noopener noreferrer"&gt;examples.tmaps.tn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source code, MIT licensed: &lt;a href="https://github.com/tmaps-tn/tmaps-snippets" rel="noopener noreferrer"&gt;github.com/tmaps-tn/tmaps-snippets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Postman collection: &lt;a href="https://www.postman.com/tmaps-tn/tmaps-api" rel="noopener noreferrer"&gt;postman.com/tmaps-tn/tmaps-api&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Vector tiles documentation: &lt;a href="https://www.tmaps.tn/documentation/api/vector-tiles" rel="noopener noreferrer"&gt;tmaps.tn/documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions or feedback? Leave a comment or write to &lt;a href="mailto:support@tmaps.tn"&gt;support@tmaps.tn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>maplibre</category>
    </item>
  </channel>
</rss>
