Map and Tile Caching
Overview
Formbird supports offline maps through vector tile caching. Vector tiles are cached by the service worker and stored in browser cache storage, enabling map display when the device is offline. The system supports multiple tile servers including the Formbird tile server (vmap.formbird.com), Vicmaps, MapBox, and MapTiler.
Vector Tiles vs Raster Tiles
Vector Tiles
- Smaller file size - Compact binary format (PBF)
- Scalable rendering - Smooth zoom at any level
- Styleable - Custom styles applied client-side
- Faster caching - Less data to download
Raster Tiles
- Pre-rendered images - PNG or JPEG
- Fixed zoom levels - Blurry when scaled
- Simpler rendering - No styling needed
- Larger storage - More data per tile
Formbird uses vector tiles for offline maps due to their efficiency.
Tile Server Options
vmap.formbird.com
Formbird's internal tile server using OpenStreetMap data:
{
"clientConfiguration": {
"openLayers": {
"tileServerGL": {
"url": "https://vmap.formbird.com/data/v3/{z}/{x}/{y}.pbf"
}
}
}
}
Vicmaps (Victoria, Australia)
Victorian Government mapping service:
{
"tileServerGL": {
"url": "https://vicmap.land.vic.gov.au/hosting/rest/services/Vicmap_Vector_Tile_Basemap_Hybrid_WM/VectorTileServer/tile/{z}/{y}/{x}.pbf",
"styleLocationUrl": "https://vicmap.land.vic.gov.au/hosting/rest/services/Vicmap_Vector_Tile_Basemap_Hybrid_WM/VectorTileServer/resources/styles/root.json"
}
}
Note: Vicmaps uses {z}/{y}/{x} order, not the standard {z}/{x}/{y}.
Available Vicmaps Basemaps:
| Name | URL Path |
|---|---|
| Colour | Vicmap_Vector_Tile_Basemap_Colour_WM |
| Dark Grey | Vicmap_Vector_Tile_Basemap_DarkGrey_WM |
| Hybrid | Vicmap_Vector_Tile_Basemap_Hybrid_WM |
| Greyscale | VicmapVectorGreyscale |
| Overlay | Vicmap_Vector_Tile_Basemap_Overlay_WM |
MapBox
Commercial mapping service:
{
"mapParameters": {
"mapViews": [
{
"uiLabel": "MapBox",
"serverType": "tilePBF",
"url": "https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/{z}/{x}/{y}.vector.pbf?access_token=YOUR_TOKEN"
}
]
}
}
MapTiler
Commercial mapping service:
{
"mapParameters": {
"mapViews": [
{
"uiLabel": "MapTiler",
"serverType": "tilePBF",
"url": "https://api.maptiler.com/tiles/v3-openmaptiles/{z}/{x}/{y}.pbf?key=YOUR_KEY"
}
]
}
}
Configuration
Basic Tile Server Configuration
{
"clientConfiguration": {
"openLayers": {
"tileServerGL": {
"url": "https://vmap.formbird.com/data/v3/{z}/{x}/{y}.pbf"
}
}
}
}
Cache Bounds Configuration
Map caching configuration is defined in clientConfiguration.openLayers.mapViewsToCache. This includes the tile URL, style URL, bounds, and zoom levels:
{
"clientConfiguration": {
"openLayers": {
"mapViewsToCache": [
{
"name": "Vicmaps Colour",
"styleLocationUrls": [
"https://vicmap.land.vic.gov.au/hosting/rest/services/Hosted/Vicmap_Vector_Tile_Basemap_Colour_WM_Hosted/VectorTileServer/resources/styles/root.json"
],
"minZoom": 1,
"maxZoom": 15,
"dataBounds": [
{
"topLeftCoord": [144.173, -37.209],
"bottomRightCoord": [144.965, -37.959]
}
],
"url": "https://vicmap.land.vic.gov.au/hosting/rest/services/Hosted/Vicmap_Vector_Tile_Basemap_Colour_WM_Hosted/VectorTileServer/tile/{z}/{y}/{x}.pbf"
}
]
}
}
}
Key properties:
- name - Display name for the cached map view
- styleLocationUrls - Array of URLs to vector tile style JSON files (required for proper rendering)
- minZoom/maxZoom - Zoom level range to cache during initial caching
- dataBounds - Geographic areas to cache using topLeftCoord and bottomRightCoord as [longitude, latitude]
- url - Tile URL pattern with {z}, {y}, {x} placeholders
Map Views Configuration
Configure multiple map views for the component:
{
"mapParameters": {
"defaultLat": -37.8,
"defaultLon": 144.9,
"minResolution": 0.211667090000847,
"maxResolution": 2116.67090000847,
"defaultZoom": 9,
"mapViews": [
{
"uiLabel": "OSM",
"serverType": "tilePBF",
"url": "https://vmap.formbird.com/data/v3/{z}/{x}/{y}.pbf",
"crossOrigin": null
},
{
"uiLabel": "Vicmap",
"serverType": "tilePBF",
"url": "https://vicmap.land.vic.gov.au/.../tile/{z}/{y}/{x}.pbf",
"styleLocationUrl": "https://vicmap.land.vic.gov.au/.../styles/root.json"
}
]
}
}
Specifying Views to Cache
Use mapViewsToCache to specify which map views to cache offline:
{
"clientConfiguration": {
"offline": {
"mapViewsToCache": ["OSM", "Vicmap"]
}
}
}
Styling
Style Location URL
Vector tiles require styling. Specify with styleLocationUrl:
{
"mapViews": [
{
"uiLabel": "Vicmap Hybrid",
"serverType": "tilePBF",
"url": "https://vicmap.land.vic.gov.au/.../tile/{z}/{y}/{x}.pbf",
"styleLocationUrl": "https://vicmap.land.vic.gov.au/.../resources/styles/root.json"
}
]
}
Default Styling
If no style URL is provided:
- OpenLayers applies default blue styling
- Vector features are still displayed
- Styling can be applied programmatically
Caching Process
How Tiles Are Cached
- Enable caching - User enables offline mode
- Calculate bounds - Get region from configuration
- Generate tile URLs - Calculate all tiles within bounds
- Fetch and cache - Download each tile URL
- Store in cache - Service worker stores responses
Cache Storage
Map tiles are cached in "Cache Storage" under tiles-UUID, where UUID is unique for each device user. This allows multiple different Formbird logins to cache map tiles on the same browser without conflicts.
// CacheMapTilesService
const cacheStorage = await caches.open('tiles-' + userUUID);
fetch(coordArray[index].url).then(async (response) => {
cacheStorage.add(coordArray[index].url);
});
To view cached map tiles in browser DevTools:
1. Open DevTools → Application → Cache Storage
2. Look for cache names starting with tiles-
Service Worker Integration
The service worker intercepts tile requests:
self.addEventListener("fetch", function(e) {
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
Zoom Levels
Tiles are cached at multiple zoom levels:
| Zoom Level | Approximate Scale |
|---|---|
| 0-4 | Continental |
| 5-9 | Regional |
| 10-14 | City/Town |
| 15-17 | Street level |
| 18+ | Building level |
Configure the zoom range for caching based on your needs.
Handling Missing Zoom Levels
Problem
Some tile servers don't provide all zoom levels. Vicmaps, for example, only goes to zoom level 16.
Solution
When a tile request fails at a higher zoom level:
- Detect failure - 404 response from tile server
- Find valid level - Find the nearest available zoom level
- Load valid tiles - Fetch from available zoom level
- Vector zoom - OpenLayers zooms the vectors smoothly
Configuration for Smooth Vector Rendering
// OpenLayers renders vectors at any zoom level
new ol.layer.VectorTile({
renderMode: 'vector', // Smooth zooming
source: vectorTileSource
});
Offline Map Display
Loading Cached Maps
When offline:
- Map component requests tile URLs
- Service worker intercepts requests
- Cache returns stored responses
- Map renders from cached data
Fallback Behavior
If a tile is not cached:
- Request fails (no network)
- Placeholder or no tile displayed
- Warning logged to console
Self-Hosted Tile Server
tileserver-gl
Run your own tile server with tileserver-gl:
# Install
npm install -g tileserver-gl
# Run with map tiles file
tileserver-gl melbourne.mbtiles
Server runs on port 8080.
Getting Map Tiles
Download mbtiles from OpenMapTiles:
- https://openmaptiles.com/downloads/
Configure in Formbird:
{
"tileServerGL": {
"url": "http://localhost:8080/data/v3/{z}/{x}/{y}.pbf"
}
}
Asset Layers from Tile Servers
MapTiler Assets
Upload GeoJSON assets to MapTiler cloud:
{
"layers": [
{
"type": "tile",
"url": "https://api.maptiler.com/data/{dataset_id}/features.json?key=YOUR_KEY",
"color": "blue",
"geoJsonField": "locationGeo"
}
]
}
MapBox Assets
Upload datasets to MapBox:
{
"layers": [
{
"type": "tile",
"url": "https://api.mapbox.com/datasets/v1/{username}/{dataset_id}/features?access_token=YOUR_TOKEN"
}
]
}
Asset Data Format
GeoJSON format for uploading:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [144.9, -37.8]
},
"properties": {
"documentId": "abc-123",
"name": "Asset Name"
}
}
]
}
Troubleshooting
Maps Not Loading Offline
- Check cache storage - Verify tiles are cached in DevTools
- Verify bounds - Ensure region is within cached bounds
- Check service worker - Confirm it's active and intercepting
- Inspect URL pattern - Verify URL matches cached pattern
Tiles Blurry When Zoomed
- Ensure
renderMode: 'vector'is set - Check if zoom level is within tile server range
- Verify vector tiles are being used (not raster)
Caching Takes Too Long
- Reduce bounds - Cache smaller region
- Reduce zoom levels - Skip higher zoom levels
- Check network - Verify connection speed
- Monitor progress - Watch for errors
Style Not Applied
- Verify styleLocationUrl - Check URL is accessible
- Check CORS - Style must allow cross-origin
- Inspect response - Verify valid JSON returned
Related Documentation
- 101-Offline-Architecture.md - System overview
- 103-Service-Workers.md - Service worker caching
- 106-Initial-Caching-Process.md - Caching workflow
- 109-Configuration-Reference.md - All configuration options