[{"data":1,"prerenderedAt":185},["ShallowReactive",2],{"footer-learn-links":3,"site-prefooter-cta":16,"blog-\u002Fblog\u002Fupdated-boundary-layers-across-zoom-levels\u002F":24,"related-blog-\u002Fblog\u002Fupdated-boundary-layers-across-zoom-levels\u002F":128,"blog-author-\u002Fblog\u002Fupdated-boundary-layers-across-zoom-levels\u002F":174},[4,7,10,13],{"title":5,"path":6},"What Is a Distance Matrix API?","\u002Flearn\u002Fdistance-matrix-api",{"title":8,"path":9},"Can You Store Geocoding Results?","\u002Flearn\u002Fgeocoding-data-storage",{"title":11,"path":12},"What Does a \"Free\" Map API Actually Cost?","\u002Flearn\u002Fwhat-does-a-free-map-api-cost",{"title":14,"path":15},"What Is the Best Geocoding API?","\u002Flearn\u002Fbest-geocoding-api",{"id":17,"extension":18,"heading":19,"meta":20,"stem":21,"text":22,"__hash__":23},"site\u002Fsite\u002Fprefooter-cta.yml","yml","Business Outcomes That Fuel Your Growth",{},"site\u002Fprefooter-cta","With Stadia Maps, you build the solutions that matter. Logistics platforms provide accurate ETAs, fleet management apps reduce fuel costs, and emergency dispatch systems improve response times.","XztWiZDFyAC0XCoeYLLQrcyaVmP8uvGWALRS354c9I4",{"id":25,"title":26,"abstract":27,"author":28,"body":29,"description":101,"extension":102,"head":27,"image":103,"imageAlt":104,"keywords":105,"meta":116,"modified":27,"navigation":117,"path":118,"proficiencyLevel":27,"published":119,"rawbody":120,"schemaOrg":27,"schemaType":27,"section":121,"seo":122,"stem":126,"__hash__":127},"blog\u002Fblog\u002Fupdated-boundary-layers-across-zoom-levels.md","Updated Boundary Layers: Consistency and Efficiency Across All Zoom Levels",null,"ian-wagner",{"type":30,"value":31,"toc":93},"minimark",[32,36,43,46,51,54,62,66,75,78,82,85],[33,34,26],"h1",{"id":35},"updated-boundary-layers-consistency-and-efficiency-across-all-zoom-levels",[37,38,39],"blockquote",{},[40,41,42],"p",{},"Until now, we had several inconsistencies in how we displayed boundaries across zoom levels. Take, for instance, the border between North Korea and South Korea. At mid-zoom levels, we drew three separate lines for the demilitarized zone. Zoom in, and it disappeared. Zoom out, and it disappeared again.",[40,44,45],{},"That happened because we used a mixture of datasets, which made it difficult to deliver a consistent product across zoom levels. A boundary that existed in the source data at zoom 8 didn't necessarily exist at zoom 4, or may have even been in a slightly different place. This also led to some boundaries being marked as disputed at some zoom levels but not others.",[47,48,50],"h2",{"id":49},"what-we-changed","What We Changed",[40,52,53],{},"We overhauled our boundary processing pipeline to remove these inconsistencies and streamlined how we serve them. Now, every boundary is consistently marked as disputed or non-disputed at every zoom level, and we've cleaned up inconsistencies, like the Korean border mentioned in the intro.",[40,55,56,57,61],{},"We've also normalized the ",[58,59,60],"code",{},"claimed_by"," property that describes which country or entity claims a border. The values are now ordered consistently across the dataset. This makes it easier to apply styling and enables us to deliver more efficient tiles.",[47,63,65],{"id":64},"an-example-of-efficiency","An Example of Efficiency",[40,67,68,69,74],{},"We applied the same boundary optimization we used for water features in our June 2026 update. Each logical boundary is now a single line, and we merge connected features that share the same attributes. For the technical details on how this works, read ",[70,71,73],"a",{"href":72},"\u002Fblog\u002Ffixing-missing-water-interactive-basemaps\u002F","How We Fixed Water Feature Rendering Across All Zoom Levels",".",[40,76,77],{},"The visual output stays the same (or even improves in a few cases!) while the tiles are typically smaller. Smaller tiles matter for apps that render millions of boundaries or run on slow connections.",[47,79,81],{"id":80},"whats-coming-next","What's Coming Next",[40,83,84],{},"We're exploring ways to better communicate who claims, recognizes, and disputes contested areas. We're still working out the best way to do this, but the end goal is to surface more nuance so you can construct the view your users expect.",[40,86,87,88,92],{},"If you're styling boundaries today and need a particular treatment for disputed areas, tell us what you need at ",[70,89,91],{"href":90},"mailto:support@stadiamaps.com","support@stadiamaps.com",". It feeds directly into what we build next.",{"title":94,"searchDepth":95,"depth":95,"links":96},"",4,[97,99,100],{"id":49,"depth":98,"text":50},2,{"id":64,"depth":98,"text":65},{"id":80,"depth":98,"text":81},"We rebuilt our boundary processing pipeline so every boundary keeps the same disputed status at every zoom level, with smaller tiles as a side effect.","md","\u002Fimages\u002Fog\u002Fupdated-boundary-layers-across-zoom-levels.png","Updated Boundary Layers: Consistency and Efficiency Across All Zoom Levels — Stadia Maps",[106,107,108,109,110,111,112,113,114,115],"boundary layers","disputed boundaries","vector tiles","zoom level consistency","claimed_by property","map cartography","tile size optimization","OpenStreetMap boundaries","basemap styling","contested borders",{},true,"\u002Fblog\u002Fupdated-boundary-layers-across-zoom-levels","2026-10-05","---\ntitle: \"Updated Boundary Layers: Consistency and Efficiency Across All Zoom Levels\"\ndescription: We rebuilt our boundary processing pipeline so every boundary keeps the same disputed status at every zoom level, with smaller tiles as a side effect.\nauthor: ian-wagner\nimage: \u002Fimages\u002Fog\u002Fupdated-boundary-layers-across-zoom-levels.png\nimageAlt: \"Updated Boundary Layers: Consistency and Efficiency Across All Zoom Levels — Stadia Maps\"\nkeywords:\n  - boundary layers\n  - disputed boundaries\n  - vector tiles\n  - zoom level consistency\n  - claimed_by property\n  - map cartography\n  - tile size optimization\n  - OpenStreetMap boundaries\n  - basemap styling\n  - contested borders\npublished: 2026-10-05\nsection: Maps\nseo:\n  title: Consistent Boundary Layers at Every Zoom Level\n  ogTitle: Updated Boundary Layers\n  description: Boundaries now carry the same disputed status at every zoom level, the claimed_by property is normalized, and merged geometry makes the tiles smaller.\n---\n\n# Updated Boundary Layers: Consistency and Efficiency Across All Zoom Levels\n\n> Until now, we had several inconsistencies in how we displayed boundaries across zoom levels. Take, for instance, the border between North Korea and South Korea. At mid-zoom levels, we drew three separate lines for the demilitarized zone. Zoom in, and it disappeared. Zoom out, and it disappeared again.\n\nThat happened because we used a mixture of datasets, which made it difficult to deliver a consistent product across zoom levels. A boundary that existed in the source data at zoom 8 didn't necessarily exist at zoom 4, or may have even been in a slightly different place. This also led to some boundaries being marked as disputed at some zoom levels but not others.\n\n## What We Changed\n\nWe overhauled our boundary processing pipeline to remove these inconsistencies and streamlined how we serve them. Now, every boundary is consistently marked as disputed or non-disputed at every zoom level, and we've cleaned up inconsistencies, like the Korean border mentioned in the intro.\n\nWe've also normalized the `claimed_by` property that describes which country or entity claims a border. The values are now ordered consistently across the dataset. This makes it easier to apply styling and enables us to deliver more efficient tiles.\n\n## An Example of Efficiency\n\nWe applied the same boundary optimization we used for water features in our June 2026 update. Each logical boundary is now a single line, and we merge connected features that share the same attributes. For the technical details on how this works, read [How We Fixed Water Feature Rendering Across All Zoom Levels](\u002Fblog\u002Ffixing-missing-water-interactive-basemaps\u002F).\n\nThe visual output stays the same (or even improves in a few cases!) while the tiles are typically smaller. Smaller tiles matter for apps that render millions of boundaries or run on slow connections.\n\n## What's Coming Next\n\nWe're exploring ways to better communicate who claims, recognizes, and disputes contested areas. We're still working out the best way to do this, but the end goal is to surface more nuance so you can construct the view your users expect.\n\nIf you're styling boundaries today and need a particular treatment for disputed areas, tell us what you need at \u003Csupport@stadiamaps.com>. It feeds directly into what we build next.\n","Maps",{"title":123,"ogTitle":124,"description":125},"Consistent Boundary Layers at Every Zoom Level","Updated Boundary Layers","Boundaries now carry the same disputed status at every zoom level, the claimed_by property is normalized, and merged geometry makes the tiles smaller.","blog\u002Fupdated-boundary-layers-across-zoom-levels","5iHtFvVJ5X4Tbq6VUXO0Wx_PXuM2prIRoGDS3iCJsCE",[129,143,158],{"title":130,"description":131,"path":132,"published":133,"keywords":134,"rawbody":142},"Water Labels Reworked: Cleaner Names, Smarter Placement, and Straits at Last","We overhauled water name labeling across our basemaps with better relevance in the tiles, cleaner names for seas and oceans, centered lake labels, and straits.","\u002Fblog\u002Fwater-labels-reworked-cleaner-names-smarter-placement","2026-08-24",[135,111,136,108,137,138,139,140,141,114],"water labels","water_name layer","label placement","symbol-placement line-center","OpenStreetMap water names","straits","map label language","---\ntitle: \"Water Labels Reworked: Cleaner Names, Smarter Placement, and Straits at Last\"\ndescription: We overhauled water name labeling across our basemaps with better relevance in the tiles, cleaner names for seas and oceans, centered lake labels, and straits.\nauthor: ian-wagner\nimage: \u002Fimages\u002Fog\u002Fwater-labels-reworked.png\nimageAlt: \"Water Labels Reworked: Cleaner Names, Smarter Placement, and Straits at Last — Stadia Maps\"\nkeywords:\n  - water labels\n  - map cartography\n  - water_name layer\n  - vector tiles\n  - label placement\n  - symbol-placement line-center\n  - OpenStreetMap water names\n  - straits\n  - map label language\n  - basemap styling\npublished: 2026-08-24\nsection: Maps\nseo:\n  title: Water Label Improvements in Basemaps\n  ogTitle: Water Labels Reworked\n  description: We overhauled water name labeling across our basemaps with better relevance in the tiles, cleaner names for seas and oceans, centered lake labels, and straits.\n---\n\n> Around 71% of the Earth's surface is covered in water. It's not something everyone thinks about when they look at their maps, but bodies of water also provide important locational context. We're in the process of reworking our cartography from the ground up. Here are some details about our recent overhaul of water name labeling.\n\n## What We Changed\n\nThe way we approached water labeling hasn't changed much since we launched around a decade ago. I had been keeping a laundry list of things to improve for a while. It started with several variations of \"X should (or should not!) be visible at zoom Y,\" and as I dug deeper, I found a few other things we could bundle into this release.\n\n### 1. Improved relevance selection in our tiles\n\nIf you can see it from space, but it's not visible till z8, that's not great! That was, unfortunately, the story of some of the world's largest lakes, including the Great Lakes and Lake Baikal.\n\n:content-twenty-twenty{after-src=\"\u002Fimages\u002Fcontent\u002Fgreat-lakes-after.png\" before-src=\"\u002Fimages\u002Fcontent\u002Fgreat-lakes-before.png\"}\n\nThe main fix here was considering a better set of factors when determining relevance. This is baked into our tile build process, so styles don't need to make any changes.\n\nWhile you may (correctly) guess that this includes more features in the low-detail tiles, we saw an unexpected improvement in tile sizes through the mid to high detail levels. We previously included many irrelevant features at mid-zoom levels. These caused frequent collisions between lower relevance labels and higher relevance ones. Removing these reduced the overall tile size and resulted in more relevant labels showing up.\n\n### 2. Cleaner labels for major water bodies\n\nWe cleaned up labels for large maritime areas and inland seas.\n\nOne of our guiding cartographic principles is to display labels in the local language by default wherever possible. In most of the world, signage is only displayed in a single language\u002Fscript, so our maps default to showing that. We may also display a \"Latin script\" name for some features to improve international readability if the place has a name in another language, like English or French.\n\nInternational waters are tricky, though, since there is no \"local language\" and they aren't part of any one country. In OpenStreetMap, these are often given a `name` tag with half a dozen languages, separated by… something. This is not always consistent, makes the map harder to read, and crowds out other labels that could provide relevant context. In short, it's not great for anyone.\n\nWe've simplified our default styling to just the common English name for these features. Smaller bodies of water like lakes and smaller inland seas will continue to be labeled as-is, with both the local name and optionally a Latinized name.\n\nThis does not change anything about the data that we ship in the vector tiles. We still include dozens of languages, and if you're localizing a map for an audience with different language preferences, you can still [customize the styles to fit your desired label language](https:\u002F\u002Fdocs.stadiamaps.com\u002Ftutorials\u002Fchanging-the-map-label-language\u002F).\n\n:content-twenty-twenty{after-src=\"\u002Fimages\u002Fcontent\u002Fcaspian-after.png\" before-src=\"\u002Fimages\u002Fcontent\u002Fcaspian-before.png\"}\n\nBesides being cleaner, this also lets us place more labels. Note how the Black Sea was conspicuously absent before. This was because the label would have clashed with Sevastopol, so it got dropped from the middle zoom levels.\n\n### 3. Improved the placement of lake centerline labels\n\nOur in-house map styles labeled lake centerlines inconsistently. They were often off-center at lower zoom levels, and the spacing wasn't consistent.\n\nThis is now fixed, and often results in more lake labels being placeable at medium zoom levels, since moving the label to the center steers clear of settlements bordering the lake. The main fix was changing the `symbol-placement` [property](https:\u002F\u002Fmaplibre.org\u002Fmaplibre-style-spec\u002Flayers\u002F#symbol-placement) from `line` to `line-center` in all of our styles. (The brilliant cartographers over at [Stamen](\u002Fstamen\u002F) actually got this right on the first try, though, so their styles didn't suffer from this issue!)\n\n:content-twenty-twenty{after-src=\"\u002Fimages\u002Fcontent\u002Flake-centerlines-after.png\" before-src=\"\u002Fimages\u002Fcontent\u002Flake-centerlines-before.png\"}\n\n### 4. Straits are here!\n\nThat we never included these in our basemaps was a historical accident. Important straits will appear as `LineString` features in the `water_name` layer, so you get beautiful labels like these.\n\n![Stadia Maps Water Label Update - Straits](\u002Fimages\u002Fcontent\u002Fstraits.png)\n\n## What This Means for You\n\nMost Stadia Maps customers don't need to do anything. If you're using our raster map tiles or a vector style hosted at [tiles.stadiamaps.com](https:\u002F\u002Ftiles.stadiamaps.com), you already have the latest and greatest styling. All the improvements mentioned above are already live.\n\nIf you customized your own style, you may need a few minor tweaks to polish things up. The area around the English Channel highlights the two types of features most likely to require styling adjustments.\n\n![The area around the English Channel highlights the two types of features most likely to require styling adjustments.](\u002Fimages\u002Fcontent\u002Fenglish-channel.png){style=\"display: block; margin-inline: auto; max-width: 100%; width: auto;\"}\n\nIf you don't see the English Channel or the Bay of Biscay, check your style for references to the `water_name` layer and make sure that your class filters include `strait` and `bay` at lower zoom levels (we generally recommend removing zoom-based filters, unless you are intentionally creating a minimalist style). And if your layer for line-based water names doesn't do so already, set the `symbol-placement` to `line-center` to get the same visual improvements we showed above.\n",{"title":144,"description":145,"path":146,"published":147,"keywords":148,"rawbody":157},"Revisiting the Cartography Behind Stamen Terrain","Our recent water layer and water label changes reshaped how Stamen Terrain renders coastlines, fjords, and lakes. Four before-and-after comparisons show the difference.","\u002Fblog\u002Frevisiting-the-cartography-behind-stamen-terrain","2026-09-14",[149,111,150,108,151,152,153,154,155,156],"Stamen Terrain","water rendering","coastline generalization","zoom level discontinuities","OpenStreetMap water data","Natural Earth","tile size","basemap styles","---\ntitle: Revisiting the Cartography Behind Stamen Terrain\ndescription: Our recent water layer and water label changes reshaped how Stamen Terrain renders coastlines, fjords, and lakes. Four before-and-after comparisons show the difference.\nauthor: ian-wagner\nimage: \u002Fimages\u002Fog\u002Frevisiting-the-cartography-behind-stamen-terrain.png\nimageAlt: Revisiting the Cartography Behind Stamen Terrain — Stadia Maps\nkeywords:\n  - Stamen Terrain\n  - map cartography\n  - water rendering\n  - vector tiles\n  - coastline generalization\n  - zoom level discontinuities\n  - OpenStreetMap water data\n  - Natural Earth\n  - tile size\n  - basemap styles\npublished: 2026-09-14\nsection: Maps\nseo:\n  title: \"Stamen Terrain: Improved Water Rendering\"\n  ogTitle: Revisiting the Cartography Behind Stamen Terrain\n  description: How processing OSM water data at every zoom level removed coastline jumps in Stamen Terrain, preserved more detail, and shrank low-zoom vector tiles.\n---\n\n> We've been taking a fresh look at the cartographic decisions at every level of our map stack. Our recent [water layer changes](\u002Fblog\u002Ffixing-missing-water-interactive-basemaps\u002F) and [water label updates](\u002Fblog\u002Fwater-labels-reworked-cleaner-names-smarter-placement\u002F) made a visible difference to the Stamen Terrain style.\n\nRendering water at low- to mid-zoom levels trades detail against tile size. We want to represent the important features without bloating the tiles with irrelevant detail.\n\nFor polygonal features like water bodies, there already exist several generalized, pre-processed global datasets at varying levels of detail. We used these in the past, but found these created visual jumps when going from one zoom level to the next.\n\nThis was sometimes because of incompatible generalization strategies. For example, many low-resolution water datasets intentionally leave out minor features like fjords, which are not strictly important for a general large-area map but are still visible from a great distance. This is fine for their intended use case, but problematic for ours.\n\nThe other broad class of problem we noticed was that switching datasets (e.g., between Natural Earth and OSM) caused larger discontinuities, as the datasets were produced independently and vary at different speeds. We addressed this by processing OSM data for every zoom level. This took some more work to process, but was absolutely worth it!\n\nFor line data, the generalization criteria are different. We, of course, want to simplify the overall shape using similar techniques to those for polygons, but \"importance\" is a bit more difficult to measure. We revisited the thresholds for inclusion at every zoom level.\n\nThe differences in [**Stamen Terrain**](\u002Fexplore-the-map\u002F#style=stamen_terrain&map=10.05\u002F47.3495\u002F9.3513) were striking enough that we've put together this screenshot tour.\n\n## What's Changed\n\nBelow are four side-by-side comparisons of the former style and the new revised version. We used Iceland, Norway, a wider view of Scandinavia, and Lake Ontario as examples. Drag the slider to compare each pair directly.\n\n**Iceland**\n\n:content-twenty-twenty{after-src=\"\u002Fimages\u002Fcontent\u002Ficeland-after.png\" before-src=\"\u002Fimages\u002Fcontent\u002Ficeland-before.png\"}\n\n**Norway**\n\n:content-twenty-twenty{after-src=\"\u002Fimages\u002Fcontent\u002Fnorway-after.png\" before-src=\"\u002Fimages\u002Fcontent\u002Fnorway-before.png\"}\n\n**Scandinavia**\n\n:content-twenty-twenty{after-src=\"\u002Fimages\u002Fcontent\u002Fscandinavia-after.png\" before-src=\"\u002Fimages\u002Fcontent\u002Fscandinavia-before.png\"}\n\n**Lake Ontario**\n\n:content-twenty-twenty{after-src=\"\u002Fimages\u002Fcontent\u002Flake-ontario-after.png\" before-src=\"\u002Fimages\u002Fcontent\u002Flake-ontario-before.png\"}\n\nAcross all examples, we've been able to preserve more detail. And, while it's harder to highlight the difference here, we've removed essentially all discontinuous coastline and waterway jumps between zoom levels.\n\nSomewhat counterintuitively, this update actually reduces vector tile size at lower zoom levels. Even though we increased the level of visual detail on the map, we got much smarter about merging contiguous bodies of water. And of course, we were also able to drop insignificant features more reliably and improve our approach to geometric simplification, both of which contributed to the reduced tile sizes.\n\nIf you look closely, you might also notice some differences in water labels between the before and after images. [You can read more about our recent overhaul of water name labeling here.](\u002Fblog\u002Fwater-labels-reworked-cleaner-names-smarter-placement\u002F)\n\n## What This Means for Your Application\n\nIf you're using [Stamen Terrain](\u002Fproducts\u002Fmaps\u002Fmap-styles\u002F), whether vector or raster, via the endpoints on our [Stamen Terrain style page](https:\u002F\u002Fdocs.stadiamaps.com\u002Fmap-styles\u002Fstamen-terrain\u002F), you're automatically getting the improved tiles. No changes needed on your end.\n\n- Water bodies and coastlines render more consistently across zoom levels, with less of the visual noise that comes from switching data sources mid-zoom\n- Lower-zoom tiles are smaller, despite showing more visual detail\n- Improved water feature labeling: maps now show significant bays, lakes, and gulfs at lower zoom levels; show labels for straits (these were not present before); and have cleaner labels for major oceans and seas\n\nFollow us for more updates as we continue updating our cartography. And if you spot anything that looks off, let us know at \u003Csupport@stadiamaps.com>.\n",{"title":159,"description":160,"path":161,"published":162,"keywords":163,"rawbody":173},"How to Build a Custom Map Style in 30 Minutes","Fork a Stadia Maps style, recolor it in Maputnik, and host the JSON yourself. A step-by-step walkthrough for making a basemap match your app's design system.","\u002Fblog\u002Fhow-to-build-a-custom-map-style-in-30-minutes","2026-10-01",[164,165,166,167,168,169,108,170,171,172],"custom map style","MapLibre style spec","Maputnik","map branding","basemap customization","Alidade Smooth","style JSON hosting","domain-based authentication","map color palette","---\ntitle: How to Build a Custom Map Style in 30 Minutes\ndescription: Fork a Stadia Maps style, recolor it in Maputnik, and host the JSON yourself. A step-by-step walkthrough for making a basemap match your app's design system.\nauthor: rob-yoegel\nimage: \u002Fimages\u002Fog\u002Fhow-to-build-a-custom-map-style-in-30-minutes.png\nimageAlt: How to Build a Custom Map Style in 30 Minutes — Stadia Maps\nkeywords:\n  - custom map style\n  - MapLibre style spec\n  - Maputnik\n  - map branding\n  - basemap customization\n  - Alidade Smooth\n  - vector tiles\n  - style JSON hosting\n  - domain-based authentication\n  - map color palette\npublished: 2026-10-01\nsection: Maps\nseo:\n  title: Build a Custom Map Style in 30 Minutes\n  ogTitle: How to Build a Custom Map Style in 30 Minutes\n  description: Fork a MapLibre style, recolor it in Maputnik, export the JSON, and host it yourself. Includes authentication setup and answers to common styling problems.\n---\n\n> This walkthrough forks a Stadia Maps style, recolors the background, water, road, and label layers in Maputnik, exports the JSON, and hosts it as a static file. It covers domain-based authentication versus API keys for production, and answers some of the failures developers hit most: blank maps caused by a 401 response; road layers that only partly change color because roads are split across layers by class; and palettes that break at higher zoom levels.\n\nYour app has a design system, but your map doesn't match it.\n\nMaybe the roads are the wrong shade of gray, the labels compete with your UI, or the entire basemap is louder than the data you're trying to put on top of it. You don't need a different map provider. You just need it to look like it belongs in your app.\n\nA [MapLibre style](https:\u002F\u002Fmaplibre.org\u002Fmaplibre-style-spec\u002F) is just a JSON file, so customizing a map shouldn't be a design problem. It should be a file you edit, review, and deploy like any other asset in your repo.\n\n## What You'll End Up With\n\nIn about 30 minutes, you'll have an interactive map that uses your full brand palette: your background color, your road hierarchy, and your label treatment. A single JSON file you host yourself, loaded by a few lines of [MapLibre GL JS](https:\u002F\u002Fmaplibre.org\u002Fmaplibre-gl-js\u002Fdocs\u002F). The end result will look something like this:\n\n![Stock Alidade Smooth and the same map with a custom brand palette applied, side by side](\u002Fimages\u002Fcontent\u002Fcustom-map-style-before-after.png){style=\"display: block; margin-inline: auto; max-width: 100%; width: auto;\"}\n\n## Start With a Working Map\n\nTo get started, all you need is a browser, a Stadia Maps account, and somewhere to serve a static file.\n\nOpen our [Build a Map](\u002Fbuild-a-map\u002F) tool (which doesn't require your Stadia Maps login). It's a style picker, not a style editor. The color changes happen in the next step.\n\nUse the tool to display a working map with your preferred map style and generate the code to load it. Styles include Alidade Bright, Alidade Smooth, Alidade Smooth Dark, Alidade Satellite, Outdoors, OSM Bright, Stamen Terrain, Stamen Toner, Stamen Toner Lite, Stamen Toner Dark, Stamen Toner Blacklite, and Stamen Watercolor.\n\nIf you don't know which style to choose, start with [**Alidade Smooth**](https:\u002F\u002Fdocs.stadiamaps.com\u002Fmap-styles\u002Falidade-smooth\u002F), which is designed for maps with a lot of markers or overlays. Its muted palette leaves you room to work. Forking a finished style also beats starting from an empty one, because you inherit years of cartographic decisions about what to show at which zoom level.\n\nSet your latitude, longitude, and zoom to frame a place you know well. You'll be judging color changes against it, so pick a spot where you'll notice when the roads look wrong.\n\nNext, click the **Try it in JSFiddle** button. You now have a working interactive map. The generated code looks like this (London is used in this example):\n\n```javascript\n\u002F\u002F This is a quick sample to get you started with an interactive map.\n\n\u002F\u002F 1. Set up the map control.\nvar map = new maplibregl.Map({\n    container: 'map',\n    style: 'https:\u002F\u002Ftiles.stadiamaps.com\u002Fstyles\u002Falidade_smooth.json',  \u002F\u002F 2. Style URL; see our https:\u002F\u002Fdocs.stadiamaps.com\u002Fthemes\u002F for more options\n    \u002F\u002F You can also explicitly request tiles from our EU servers using the following URL:\n    \u002F\u002F https:\u002F\u002Ftiles-eu.stadiamaps.com\u002Fstyles\u002Falidade_smooth.json\n    center: { lat: 51.5072, lng: -0.1276 },  \u002F\u002F 3. Initial focus coordinate\n    zoom: 7,  \u002F\u002F 4. Initial zoom\n});\n```\n\nThe HTML pane loads MapLibre GL JS and its stylesheet, and the JavaScript pane adds a `setRTLTextPlugin` call, so right-to-left labels render correctly. Keep this tab open. That `style` line is the only one you'll change at the end.\n\nIf your users are in the EU and you want tiles served from EU infrastructure, the code notes the alternative endpoint: `https:\u002F\u002Ftiles-eu.stadiamaps.com\u002Fstyles\u002Falidade_smooth.json`.\n\nYou have a map, and you know which line controls its appearance. Next, you'll change what that line points to.\n\n## Customize the Style in Maputnik\n\n[Maputnik](https:\u002F\u002Fmaputnik.github.io\u002Feditor\u002F) runs in the browser. It's free and open source, and it edits the same JSON your map already loads.\n\n**Open your starting style.** In the Maputnik menu bar, choose **Open**, then enter the JSON URL for the style you picked. For Alidade Smooth, that's `https:\u002F\u002Ftiles.stadiamaps.com\u002Fstyles\u002Falidade_smooth.json`. The full list lives in our [style library documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fthemes\u002F).\n\n**Find the layers that matter.** A production basemap has many [layers](https:\u002F\u002Fdocs.stadiamaps.com\u002Fvector\u002F), but these are the most important to focus on:\n\n- Background and landcover, basically the base color everything sits on\n- Water, usually the strongest color contrast on the map\n- Roads, split across several layers by class, which is why changing \"the road color\" means changing more than one thing\n- Labels, including text color, halo color, and font\n\nUse Maputnik's layer filter to search by name instead of scrolling. Change the background first and let it set the range everything else has to work within.\n\n**Match your palette and check your contrast.** Paste in your brand hex values, then zoom from country level to street level. Colors that look right at [zoom 7](https:\u002F\u002Fwiki.openstreetmap.org\u002Fwiki\u002FZoom_levels) often fall apart at zoom 15, when [more layers switch on](https:\u002F\u002Fmaplibre.org\u002Fmaplibre-style-spec\u002Flayers\u002F) at their `minzoom` thresholds. Check the label text against the [WCAG minimum of 4.5:1](https:\u002F\u002Fwww.w3.org\u002FWAI\u002FWCAG22\u002FUnderstanding\u002Fcontrast-minimum.html) while you're here, since a palette that passes on a white page can fail over landcover fills. Most of the time, what you spend here determines whether a map looks branded or broken.\n\nCheck the [attribution requirements](\u002Fattribution\u002F) for the style you pick. Keep in mind that Stamen styles carry their own license terms for commercial use and remixing. Also, Stamen Watercolor is a raster style, so it isn't vector-styleable.\n\nClick **Export** in the top menu and save the JSON. If you'll be loading tiles with an [API key](https:\u002F\u002Fdocs.stadiamaps.com\u002Fauthentication\u002F), which covers mobile apps, server-side rendering, and anything outside a browser, enter your API key in the export dialog, and [Maputnik writes it into the style for you](https:\u002F\u002Fdocs.stadiamaps.com\u002Fcustom-styles\u002F).\n\nYou now have your style as a file. All that's left is putting it somewhere your app can reach.\n\n## Host Your Style and Ship It\n\nSome mapping platforms keep your style on their servers, so this step never comes up. We hand you the file instead. Your style is a portable artifact you own: you can diff it, review it in a pull request, roll it back, bundle it offline, and take it with you. It's a design asset in your repository, not a row in someone else's database.\n\n**Host the exported JSON** anywhere you serve static files: your own server, a CDN, or bundled inside your app.\n\n**Point your map at it.** Go back to that JSFiddle tab and change one line:\n\n```javascript\nvar map = new maplibregl.Map({\n    container: 'map',\n    style: 'https:\u002F\u002Fyourdomain.com\u002Fstyles\u002Fyour-custom-style.json',  \u002F\u002F your style now\n    center: { lat: 51.5072, lng: -0.1276 },\n    zoom: 7,\n});\n```\n\n**Reload.**\n\n**Set up authentication before you go live.** For production websites, register your domain in the [Stadia Maps dashboard](https:\u002F\u002Fclient.stadiamaps.com\u002Fdashboard\u002F) and use [domain-based authentication](https:\u002F\u002Fdocs.stadiamaps.com\u002Fauthentication\u002F) to keep API keys out of your client code. For mobile apps, server-side code, and intranet sites, use an API key. Local development on `localhost` requires no authentication, which is why your fiddle worked immediately.\n\n## Troubleshooting and Common Questions\n\n### Why is my map blank after switching to my custom style?\n\nCheck the browser console. A blank map with a 401 response is an authentication issue. Either your domain isn't registered yet, or your API key didn't make it into the style. A blank map with no network errors usually indicates a malformed export or an invalid style URL.\n\n### Why didn't some layers change color?\n\nRoads and labels are split across multiple layers by class and zoom level, so changing one road layer changes only one road class. Filter the layer list by name and check for siblings.\n\n### Why do my colors look right at low zoom but wrong at high zoom levels?\n\nLayers switch on as you zoom in, and some properties use zoom-dependent expressions rather than fixed values. Test every color change across the full zoom range before committing to it.\n\n### Do I have to re-export when the base style is updated?\n\nYour exported style is a snapshot. It keeps working as-is, but it won't automatically pick up upstream improvements. When an update ships that you want, re-fork and reapply your changes, which is much faster if your palette is documented in your repository.\n\n### Can I use custom icons and fonts?\n\nYes, though both take more setup than anything else here. Generate sprite files with [Spreet](https:\u002F\u002Fgithub.com\u002Fflother\u002Fspreet), host them yourself, and point your style's `sprite` key at them. [Our docs cover the details](https:\u002F\u002Fdocs.stadiamaps.com\u002Fcustom-styles\u002F#advanced-customizing-sprites), including why the URL leaves off the file extension. For fonts, generate glyphs with our own `build_pbf_glyphs` or [MapLibre Font Maker](https:\u002F\u002Fmaplibre.org\u002Ffont-maker\u002F); [the font docs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fcustom-styles\u002F#advanced-customizing-fonts) explain how to combine scripts into a single stack with fallbacks. Check the license on anything you ship.\n\n## Take the Next Step\n\nYou now have a branded basemap and a repeatable process for changing it. From here, the natural next steps are adding your own data layers on top, swapping in custom marker sprites, or building a dark variant from the same palette. Our [custom styling documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fcustom-styles\u002F) goes deeper on sprites and glyphs when you're ready.\n\nReady to [get started with Stadia Maps for free](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F)? Every new account includes a 14-day trial of Stadia Maps Professional, and we don't require a credit card when you sign up. Need help? [Reach out to our Support team at any time.](\u002Fsupport\u002F)\n",{"id":175,"bio":176,"extension":18,"jobTitle":177,"meta":178,"name":179,"sameAs":180,"slug":28,"stem":182,"twitterCreator":183,"type":27,"url":27,"__hash__":184},"authors\u002Fauthors\u002Fian-wagner.yml","Ian is co-founder of Stadia Maps and leads engineering and operations.","Founder & Chief Architect",{},"Ian Wagner",[181],"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fian-w-wagner\u002F","authors\u002Fian-wagner","@ianthetechie","duXv7qvc_ceMszbExfddzNJaKYo_d7bxEXGpG1-tWQU",1791213286355]