High-quality vector maps for millions of users, served from the edge at a fraction of the cost of legacy platforms.
Platform
Traditional mapping platforms are expensive and slow. Tango Maps is a mapping platform built to be fast, scalable and affordable.
Standard vector tiles that drop into MapLibre GL, Leaflet and any client that speaks MVT.
Tiles are cached close to your users on a global CDN, so maps load fast wherever they are.
One tile URL and a style. Swap it into your existing map and keep the same app experience.
Pay-as-you-go pricing keeps your bill predictable as you grow to millions of map views.
Developers
Tango Maps serves standard Mapbox Vector Tiles. Point your existing MapLibre or Leaflet map at our CDN, or hand one prompt to your AI coding assistant and let it wire up the map for you.
Paste this into Claude Code, Cursor, Copilot or any AI coding assistant. It explains how Tango Maps works and adds a map to your project with your key.
Add a map to this project using Tango Maps, a vector map tile service compatible with MapLibre GL JS and Leaflet.
## Account details
- API key: YOUR_API_KEY
- TileJSON URL: https://cdn.tangomaps.com/map4.json?key=YOUR_API_KEY
The key is a publishable browser key. It only works on the domains allowed in the Tango Maps dashboard (localhost always works), so it is safe in frontend code. Store it in a public environment variable following this project's conventions (for example VITE_TANGO_MAPS_KEY or NEXT_PUBLIC_TANGO_MAPS_KEY) and add the variable to .env.example.
## How Tango Maps works
- Tiles are Mapbox Vector Tiles using the Protomaps basemap v4 schema (OpenStreetMap data), zoom 0-15. MapLibre overzooms past 15 automatically.
- Every map must start from the TileJSON URL. Each TileJSON request counts as one map load and returns signed tile URLs that are valid for 24 hours. Never hardcode or build tile URLs yourself; tile requests without a valid signature are rejected.
- Requests must come from a web page on an allowed domain, because the key is checked against the Origin or Referer header. Server-side requests, file:// pages and native mobile apps are not supported.
- Style the map with the @protomaps/basemaps package: layers(sourceName, namedFlavor(flavor), { lang }). Flavors: light, dark, white, grayscale, black. lang is a language code such as en or es.
- Glyphs: https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf
- Sprite: https://protomaps.github.io/basemaps-assets/sprites/v4/<flavor> (use the same flavor as the layers)
- Keep the OpenStreetMap attribution visible. MapLibre shows it automatically from the TileJSON; with Leaflet pass tilejson.attribution to the layer.
## Implementation
1. Check which map library the project already uses:
- MapLibre GL JS: replace the current style with the Tango Maps style below.
- Mapbox GL JS: switch to maplibre-gl@5, which has a compatible API, then use the style below.
- Leaflet: install protomaps-leaflet, fetch the TileJSON first and pass tilejson.tiles[0] as the url option of leafletLayer, with flavor, lang and attribution.
- Google Maps or no map yet: install maplibre-gl@5 and @protomaps/basemaps (version 5 works with every bundler without extra setup) and build a reusable map component that follows this project's framework conventions (React, Vue, Svelte, Angular, plain JS), removing the map on unmount with map.remove().
2. Keep existing markers, popups, layers, controls and interactions working by porting them to the equivalent MapLibre or Leaflet APIs.
3. Give the map container an explicit height, otherwise it renders with zero height.
4. Use this style with MapLibre GL JS:
```js
import { layers, namedFlavor } from '@protomaps/basemaps';
const style = {
version: 8,
glyphs: 'https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf',
sprite: 'https://protomaps.github.io/basemaps-assets/sprites/v4/light',
sources: {
tango: { type: 'vector', url: 'https://cdn.tangomaps.com/map4.json?key=YOUR_API_KEY' }
},
layers: layers('tango', namedFlavor('light'), { lang: 'en' })
};
```
## Troubleshooting
- 401 "Invalid API key": the key is wrong or was revoked.
- 403 "This API key is not allowed on <host>": add that domain to the key in the Tango Maps dashboard (https://tangomaps.com/app/keys).
- 401 "Missing or expired tile session": tiles were requested without going through the TileJSON URL, or a page stayed open for more than 24 hours. Load the style again to refresh it.
- 429: the free plan's monthly map loads are used up; upgrade at https://tangomaps.com/app/billing.
- "Worker failed to load": the project uses maplibre-gl 6, which has no default export and needs its worker URL set. Either use maplibre-gl@5, or with Vite import the worker with `import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?url'` and call `setWorkerUrl(workerUrl)` (a named export of maplibre-gl 6) before creating the map.
## Verify
Run the dev server on localhost, open the page with the map and confirm that streets and labels render, and that requests to cdn.tangomaps.com return 200 in the browser's network panel.Pricing
Pay up to 90% less than Google Maps, with simple usage-based pricing.
Prototype and ship side projects.
$0
50K map loads / mo
Hard cap, no surprise bills
Start buildingFor products with real traffic.
$49 / mo
500K map loads / mo
$0.40 per 1K after that
Start with GrowthFor high-traffic apps that need a hand.
$249 / mo
3M map loads / mo
$0.25 per 1K after that
Start with ScaleFor platforms serving maps at national scale.
Custom
Custom volume
Billed monthly or annually
Talk to usPrices in USD. A map load is counted each time a map is initialized with your API key on an allowed domain; panning and zooming within it are included. Savings compared with Google Maps Platform Dynamic Maps list prices.
Enterprise
Tell us about your traffic and requirements. We'll put together volume pricing, a dedicated tile deployment and a migration plan from your current provider.