Map Viewport Loading¶
This page describes how to efficiently load data into interactive map applications using the Solar Lake Enterprise API.
The API provides optimized bounding box endpoints designed specifically for viewport-based loading.
Overview¶
For map applications, the typical workflow is:
- User pans or zooms the map
- Frontend calculates the visible bounding box
- API request loads data for that bounding box
- Map updates with returned features
There are two levels of viewport endpoints:
- GET endpoints → simple
- POST endpoints → advanced (filtering, projection, exclusion, pagination)
Choosing the Right Endpoint¶
Use GET /bbox/... when:¶
- You only need basic viewport loading
- Small geographical extent
- No filtering is required
- You want a simple request format
Example:
GET /bbox/h3s?min_lon=11.5&min_lat=48.1&max_lon=11.51&max_lat=48.11&subscription_key=YOUR_KEY
Use POST /bbox/... when:¶
- You need filtering
- You want to reduce payload using
options.select - You want incremental loading
- You need pagination
- You want fine-grained control
Example:
POST /bbox/buildings?subscription_key=YOUR_KEY
{
"bbox": {
"min_lon": 11.5,
"min_lat": 48.1,
"max_lon": 11.51,
"max_lat": 48.11
},
"filter": {
"pv": false,
"roof_area": { "$gte": 80 }
},
"options": {
"select": ["building_id", "roof_area", "pv", "geometry"],
"limit": 5000
}
}
Viewport Strategy Options¶
Depending on your frontend, you may choose different data layers.
1️⃣ Aggregated Layer (H3 Hexagons)¶
Use:
GET /bbox/h3s
or
POST /bbox/h3s
Advantages:
- Smaller payload
- Scales well at low zoom levels
- Suitable for choropleth maps
- Includes geometry + aggregate metrics
Typical fields:
h3_idcount_buildingssales_opportunity_scoreshare_ownedgeometry
Optional: Rendering Empty H3 Cells¶
Map clients may optionally request empty H3 cells within the viewport.
This can be useful when rendering a faint grid overlay or background shading that helps users visually understand areas without residential buildings.
Example request:
{
"bbox": { ... },
"include_empty_cells": "geometries"
}
Recommended visualization approach:
- Render normal cells (
items) using the chosen color scale - Render empty cells (
empty_items) with a light neutral color or faint outlines - Disable hover and interaction for empty cells
This allows users to distinguish between:
- areas with residential buildings (cells with data)
- areas without residential buildings (empty cells)
Performance Considerations¶
Returning empty cells increases the response size because additional geometries must be transmitted.
For best performance:
- enable empty cells only when needed
- use
options.selectto limit returned fields - avoid very large bounding boxes
2️⃣ Postcode or Municipality Layer¶
Use:
GET /bbox/postcodes
GET /bbox/municipalities
or
POST /bbox/postcodes
POST /bbox/municipalities
Good for:
- Administrative boundary visualization
- Regional dashboards
- Sales territory analysis
- Planning of mailings
3️⃣ Building Layer (Detailed Views)¶
Use:
GET /bbox/buildings
or
POST /bbox/buildings
Recommended only at higher zoom levels due to payload size.
Always use projection:
{
"options": {
"select": ["building_id", "roof_area", "pv", "geometry"]
}
}
Incremental Loading (Avoid Re-Downloading Data)¶
When users pan slightly, you do not need to reload the entire viewport.
The advanced POST endpoints support exclusion of already loaded areas:
{
"bbox": {
"min_lon": 11.5,
"min_lat": 48.1,
"max_lon": 11.51,
"max_lat": 48.11
},
"exclude": {
"exclude_bboxes": [
{
"min_lon": 11.505,
"min_lat": 48.105,
"max_lon": 11.51,
"max_lat": 48.11
}
]
},
"options": {
"select": ["building_id", "geometry"]
}
}
This allows efficient incremental viewport updates.
Recommended Frontend Architecture¶
A typical map integration looks like this:
- Track current viewport bounds
- Debounce map move events (e.g., 200–400 ms)
- Cancel previous in-flight request
- Send new bbox request
- Render returned GeoJSON
Pseudo-flow:
onMapMoveEnd():
bbox = getMapBounds()
requestData(bbox)
Performance Recommendations¶
For smooth map interaction:
- Always use
options.selectto minimize payload - Avoid extremely large bounding boxes
- Use aggregate layers for low zoom levels
- Switch to building layer only when zoomed in
- Use incremental loading when possible
Understanding BBox Responses¶
Bounding box responses include metadata:
{
"h3_resolution": 7,
"cells": 120,
"returned": 5000,
"items": [...]
}
Where:
h3_resolution→ resolution used for aggregationcells→ number of grid cells covering the bboxreturned→ number of records returneditems→ actual data
This metadata can be used for diagnostics or analytics but is not required for rendering.
Common Pitfalls¶
Large Payloads¶
Returning full building records for large areas may impact performance.
Use projection.
Excessive Requests¶
Debounce map movement to avoid flooding the API.
Geometry Handling¶
All geometries are GeoJSON.
Make sure your mapping library expects [lon, lat].
Summary¶
For interactive maps:
- Use aggregate layers at low zoom
- Use building layer at high zoom
- Prefer POST endpoints for flexibility
- Always use projection
- Implement incremental loading for best performance