In vector cartography, the map is only as good as the data that powers it. If we don’t understand what’s going on in the underlying data, we’re pretty limited in our cartographic approach. A major part of this work involves parsing vector tile data, determining how one dataset compares to another, and diagnosing bugs encountered during the design process.
As part of our cartography work at Stamen, we’ve developed several tools to help make map design projects of any size faster, easier, and more collaborative. In this blog post we’ll outline some ways that we debug using our open source tools, complemented by some non-Stamen tools we like as well. A few of these tools were recently highlighted in Awesome Maplibre: A collection of awesome things that use or support MapLibre! – we’re glad others find them useful, too!
When putting ideas for this post together, the team found that there are many different types of debugging that we routinely encounter on cartography projects, each requiring slightly different solutions. These roughly fall into a few buckets: understanding data, finding issues with stylesheets, and optimizing how tiles and styles work together.
Understanding data
Often, clients will have a general idea of the primary use case for their cartography project when they first come to us. Usually (but not always!), they bring data with them from one of a handful of data providers and formats we are familiar with (i.e. OSM, HERE, Tilezen, Mapbox, OpenMapTiles, etc.) that meshes well with the type of map we are creating. This is ideal for us, as we have worked with all of these sources many times before and are well aware of what features and attributes they have available.
Sometimes, a client will have their own version of an existing dataset with modifications for their use case, such as a cut of OSM tiles with additional data added or unneeded data removed. One of our core tools, Maperture, allows us to easily investigate what the tiles contain if we have a style to start from. You can select any feature and see a pop-up with its attributes clearly listed:
Another tool we love for this use case is Vector Inspector, created by friend of Stamen Steve Bennett, which renders all features from an endpoint as separate layers on a simple basemap. This can be incredibly helpful, as it shows you everything available in the tiles:
Vector Inspector has the added benefit of letting you see all possible values within a given view, where you can select and highlight a specific value you may be looking for:
Between these two, Maperture is best for comparing sources to one another in a single pane, assuming you have styles that use them already (for example, comparing how an area looks with pure OSM data vs. with Mapbox data).
You can also interrogate multiple tile sources at once in Maperture, whereas Vector Inspector is limited to one endpoint at a time. This is useful for many of our clients, who often have a core set of tiles powering their basemap with an additional source like traffic or custom points of interest as well.
We love the concept of an “x-ray mode”, where you can see all the data in your tiles, lightly styled, with some indication of what is currently rendered by your styles. Mapbox’s version of this is great, but we don’t often work in Mapbox Studio given it requires sources hosted by Mapbox. Maputnik has a version of this too called “inspect view“, but it requires a TileJSON in order to see all the data, which our clients often don’t have. X-ray mode is an area where we’re thinking about how to improve our open source tooling to solve some of these problems.
We often develop using MapLibre, as many of our clients have moved towards using open source software where possible. Maperture allows you to compare differences in rendering between MapLibre GL, Mapbox GL, Leaflet, and so on. The more developed MapLibre GL becomes, the more we will start to see noticeable differences between MapLibre GL and Mapbox GL.
Both Maperture and Vector Inspector make it easy to interrogate our tiles and understand where data is or isn’t, where it first appears as we zoom in, and where attributes might not be what we expect. Maperture is at the core of our development environment as we work on vector cartography at scale.
Finding issues with stylesheets
One of our top debugging use cases is figuring out why stylesheet properties aren’t having the intended effect on our tiles. When used in concert with our Map GL Style Build tooling, we can easily iterate on stylesheet development and see how the output differs from our production style:
These tend to be either data issues (known or unknown) or bugs in how the stylesheet is written. Stylesheet authoring is an art, not a science – there are often a few ways to tackle a specific problem and pros and cons for each approach.
Maperture has great renderer error messages if you open the console, which helps tremendously when figuring out why something is not working.
You can also check for regressions or unintended changes with our highlight differences mode, which will scan the old and new versions of your style and call out any changes. It can find even the tiniest change, which can be very helpful when iterating on complicated styling.
Sometimes, there’s an issue in how we’ve written a filter in the stylesheet – perhaps an expression is formatted incorrectly or we’re using the wrong expression type for a given attribute. In other cases, everything may be written with proper syntax, but the values we are searching for in the tiles don’t match exactly (ex. we are looking for class == primary
but it should actually be kind == primary
).
Most often, bugs involve combinations of feature attributes that aren’t written properly. We don’t have great tooling for finding these combinations (ex. we need both class == primary
and link == true
to select and style ramps for primary roads), but this is another issue we would really like to solve.
We have an interactive legend tool called Chartographer that is immensely helpful in calling out stylesheet inconsistencies. Perhaps both major and minor city labels look fine on their own, but something about how they work together on the map is off. With Chartographer, you can easily see how colors, line widths, and symbol layers render at each zoom level.
It can be much easier to pinpoint the cause of an issue (ex. maybe one layer appears too late or changes styling at a different zoom level than intended) when you have a nice cross-section of your style.
Chartographer is purely style-based, though, so don’t expect any insight into how styling and data interact with one another.
When we find inconsistencies in styles, we use Map GL Style Build to address them and, often, prevent them from regressing or happening again elsewhere down the line. Map GL Style Build allows for as much variablization as you want in whatever format works best for your setup.
For example, if we want all of our 70+ road layers to start with one set of colors and transition to a different set as you zoom in, we can set this up to happen the same way across them all with variables. You can variablize entire expressions, which really helps reduce the amount of human error working on multiple styles can introduce.
Map GL Style Build is great for quick iteration when you have multiple stylesheets and provides helpful error messaging when something isn’t set up or written properly. To really up your debugging game, Map GL Style Build is flexible enough to allow for a debugging style setup if the other tooling we’ve talked about isn’t providing the type of insight you need. Setting up a new style takes a bit of effort with Map GL Style Build, but it makes the process so much smoother later that we find it to be more than worth the time upfront.
A custom debug style doesn’t have to be as elaborate as creating your own complete x-ray style; you can also easily make a duplicate of your current style and just add a simple additional debug layer to it. This can be especially useful if you only need to debug a specific aspect of your style, or to hunt down uncommon features in the data to make sure you’re styling them correctly.
Optimizing how tiles and styles work together
Another major area we focus on when debugging is performance optimization. With vector cartography, the source of performance issues is most often the tiles themselves rather than the stylesheet. Vector Inspector makes it very easy to see all the attributes available in tiles, especially those your stylesheets aren’t using. Assuming your tiles aren’t supporting other styles or uses for your product, unused attributes are a simple way to improve tile size and, ultimately, stylesheet performance.
On the stylesheet side, we have a sense of how performant a map is based on its number of layers, expression complexity, and additional assets required, like fontstacks and spritesheets. We will frequently go through styles in Map GL Style Build and purge anything not used in stylesheets. We use linters internally to optimize less performant expressions or simplify expressions where possible without compromising the map’s look.
Diagnosing major performance issues, like stylesheet authorship, is by no means an exact science. So many factors come into play when loading a map on a device (such as device type, network connection, caching, etc.) that it can be hard to tell what might be causing major issues. Having more helpful tooling that can make it easier to debug the entire stack would be another great area for us to explore in the future.
How do you debug?
We hope this was an interesting peek behind the curtain at how Stamen works quickly and efficiently on vector cartography projects. Stamen uses all of these tools together and they are part of our special sauce – let us know if we can help improve your mapping workflows or jumpstart a cartography project you’ve been thinking about.
If you’d like to learn more about our tooling, we’ll be talking about some of these workflows at the upcoming State of the Map US 2025 in Boston, MA. Hope to see you there!
Are there any handy tools we’ve missed? What map style debugging pain points do you wish these tools could solve? Building and maintaining these tools is important to us and there is always room for improvement! Drop us a line with any thoughts or questions.