Using Vector Tiles with Mapping Libraries
Learn how to integrate Geog vector tiles into popular mapping libraries including Mapbox GL JS, MapLibre GL JS, and Leaflet.
Mapbox GL JS
import mapboxgl from "mapbox-gl";
const map = new mapboxgl.Map({
container: "map",
style: {
version: 8,
sources: {
"geog-tiles": {
type: "vector",
tiles: [
"https://tiles.geog.dev/{z}/{x}/{y}.mvt?key=your-api-key",
],
maxzoom: 14,
},
},
layers: [
{
id: "places",
type: "circle",
source: "geog-tiles",
"source-layer": "places",
paint: {
"circle-radius": 6,
"circle-color": "#FF6B6B",
},
},
{
id: "roads",
type: "line",
source: "geog-tiles",
"source-layer": "roads",
paint: {
"line-color": "#333",
"line-width": 2,
},
},
],
},
});
MapLibre GL JS
import maplibregl from "maplibre-gl";
const map = new maplibregl.Map({
container: "map",
style: {
version: 8,
sources: {
"geog-vector": {
type: "vector",
tiles: [
"https://tiles.geog.dev/{z}/{x}/{y}.mvt?key=your-api-key",
],
},
},
layers: [
{
id: "boundaries",
type: "line",
source: "geog-vector",
"source-layer": "boundaries",
paint: {
"line-color": "#666",
"line-width": 1,
},
},
],
},
});
Leaflet with Vector Grid
import L from "leaflet";
import "leaflet.vectorgrid";
const map = L.map("map").setView([40.7128, -74.006], 10);
const vectorTileOptions = {
vectorTileLayerStyles: {
places: {
radius: 6,
fillColor: "#FF6B6B",
color: "#333",
weight: 1,
opacity: 1,
fillOpacity: 0.8,
},
roads: {
color: "#333",
weight: 2,
opacity: 0.7,
},
},
subdomains: [],
// key passed via URL query parameter
};
const vectorGrid = L.vectorGrid
.protobuf(
"https://tiles.geog.dev/{z}/{x}/{y}.mvt?key=your-api-key",
vectorTileOptions,
)
.addTo(map);
Styling Examples
Places Styling
// Restaurant categories with different colors
const placesPaint = {
"circle-radius": ["interpolate", ["linear"], ["zoom"], 8, 4, 14, 8],
"circle-color": [
"match",
["get", "category"],
"restaurant",
"#FF6B6B",
"retail",
"#4ECDC4",
"accommodation",
"#45B7D1",
"entertainment",
"#96CEB4",
"#DDD",
],
"circle-opacity": 0.8,
"circle-stroke-color": "#FFF",
"circle-stroke-width": 1,
};
Road Classification
// Different road types with varying widths
const roadsPaint = {
"line-color": "#333",
"line-width": [
"match",
["get", "class"],
"highway",
4,
"primary",
3,
"secondary",
2,
"tertiary",
1.5,
1,
],
"line-opacity": ["interpolate", ["linear"], ["zoom"], 8, 0.6, 12, 1],
};
Performance Optimization
Caching Strategy
- CDN Caching: Tiles cached at Cloudflare edge locations
- Browser Caching:
Cache-Control: max-age=86400for stable tiles - Conditional Requests: ETag support for efficient updates
Request Optimization
// Batch tile requests
const tilePromises = [];
for (let x = startX; x <= endX; x++) {
for (let y = startY; y <= endY; y++) {
tilePromises.push(
fetch(`https://tiles.geog.dev/${z}/${x}/${y}.mvt?key=${apiKey}`),
);
}
}
const tiles = await Promise.all(tilePromises);
Memory Management
// Implement tile cleanup for long-running applications
map.on("sourcedata", (e) => {
if (e.isSourceLoaded && e.sourceId === "geog-tiles") {
// Clean up old tiles beyond viewport
cleanupTileCache();
}
});
Usage Analytics
Tile Request Tracking
// Track tile usage in your application
function trackTileUsage(z, x, y, loadTime) {
analytics.track("tile_loaded", {
zoom: z,
tile_x: x,
tile_y: y,
load_time_ms: loadTime,
user_agent: navigator.userAgent,
});
}
// Monitor tile loading performance
const startTime = performance.now();
fetch(tileUrl).then((response) => {
const loadTime = performance.now() - startTime;
trackTileUsage(z, x, y, loadTime);
return response;
});
Best Practices
Client Implementation
- Implement proper error handling for missing tiles
- Use appropriate zoom levels based on data availability
- Cache tiles client-side when possible
- Implement progressive loading for better UX
- Monitor rate limits and implement backoff strategies
Performance Tips
- Limit concurrent requests to avoid rate limiting
- Use tile pyramids efficiently (don't skip zoom levels)
- Implement viewport-based loading to minimize requests
- Use compression (gzip) for faster downloads
- Monitor tile load times and optimize accordingly
Styling Guidelines
- Progressive enhancement - style for different zoom levels
- Consistent symbology across zoom levels
- Readable labels with appropriate font sizing
- Color accessibility for different user needs
- Performance-conscious styling to maintain smooth interaction
See Also
- Vector Tiles API Reference - Endpoints, parameters, and response formats
- Token Exchange Guide - Secure frontend authentication
- Error Handling Guide - Error handling patterns