A map-based project filter for an industrial supplier
A React island that shows Bolckmans' construction references as map pins and a synchronized list — filter by project type, click a pin to scroll the card into view, click a card to fly to the pin. Built during my time at Volta.
Bolckmans is a Belgian distributor of construction materials with a few hundred completed projects — office buildings, residential towers, schools. The content team wanted a reference page that let visitors answer “has anyone used this product near me?” without scrolling a flat list. The result is this map view, a React island I built on top of the existing Drupal site.
Whole site was mine at build time; the interesting island is this one. Design by Volta.
The interaction shape
The page is split: a map on one side, a filterable list on the other. Everything is bi-directional:
- Filter a project type — map pins and list cards filter together; the map re-fits its bounds to the remaining pins
- Click a pin — the matching card scrolls into view and highlights
- Click a card — the map flies to the pin, zooms in, opens the popup
The filter state is URL-synced so a sales rep can link a prospect to “office buildings in Antwerp” and it resolves directly.
Where the work actually lived
Three places that took longer than they should have:
Map bounds math. Fitting the map to a filtered subset sounds trivial, but you have to handle: empty result sets (don’t zoom to whole-world), single-pin sets (don’t zoom to maximum — pick a sensible radius), clusters near the antimeridian (irrelevant for Belgium, but the logic has to be right), and respect a minimum padding so pins don’t sit flush against the viewport edge.
Marker clustering at the right zoom levels. Leaflet’s cluster plugin gives you clustering for free, but the defaults cluster too aggressively for a country the size of Belgium. Tuning the distance threshold so Antwerp’s projects stay visible at country zoom but don’t merge with Ghent’s was a half-day of trial and error against real data.
List ↔ map scroll synchronization. Easy to write, hard to make feel good. Scrolling a card into view works, but only if you don’t steal scroll focus mid-interaction; clicking a pin when the card is already on-screen should not re-scroll. The logic ends up being a small state machine around “who initiated the focus change.”
What shipped
Straight Leaflet, no fancy map library on top. The Drupal backend
publishes all projects as a single JSON endpoint with coordinates and
taxonomies pre-resolved — same shape as the Het Bolwerk filter, because
once you’ve done it once you do it that way forever. Filtering is a
plain .filter() chain; the map and list both subscribe to the same
filtered array.
About 500 lines of React for the whole thing, including the bounds math and the scroll choreography. The slow parts were the editorial decisions — which taxonomies to surface, how granular the filters should be — not the code.