Choosing the Right Framework
The foundation of any advocacy mapping platform rests on selecting the appropriate JavaScript rendering library. Three frameworks dominate the open-source landscape:
- Leaflet - Lightweight, DOM-based
- MapLibre GL JS - WebGL hardware-accelerated
- OpenLayers - Enterprise-grade, feature-rich
Each has distinct architectural paradigms affecting performance, scalability, and suitability for specific use cases.
Leaflet
Architecture
Leaflet operates as a lightweight, DOM-based two-dimensional rendering engine using HTML elements and SVG for vector drawing.
Key Characteristics
| Aspect | Details |
|---|---|
| Bundle Size | ~40KB minified/gzipped |
| Rendering | DOM manipulation (HTML/SVG) |
| License | BSD-2-Clause |
| Plugin Ecosystem | Extensive third-party plugins |
Advantages
- Ultra-lightweight - Minimal payload ideal for low-bandwidth areas
- Fast initialization - No heavy graphics processing needed
- Simple API - Gentle learning curve
- Native DOM - Excellent screen reader accessibility
- Permissive license - No unexpected fees
Limitations
- Performance degrades past ~5,000 features
- DOM manipulation becomes slow with dense data
- Raster-focused - Limited vector tile support
Best Use Cases
- Simple checkpoint maps
- Mobile users in rural/border areas with poor connectivity
- Quick deployment with minimal configuration
- Accessibility-critical applications
MapLibre GL JS
Architecture
MapLibre uses WebGL for hardware-accelerated rendering, processing vector tiles natively in the browser.
History
MapLibre emerged as a community-driven fork of Mapbox GL JS after Mapbox transitioned to a proprietary license. It maintains full compatibility while remaining truly open-source.
Key Characteristics
| Aspect | Details |
|---|---|
| Bundle Size | Moderate to heavy |
| Rendering | WebGL hardware-accelerated |
| License | BSD-3-Clause |
| Data Format | Vector tiles (.pbf) |
Advantages
- Scales efficiently - Handles millions of features
- Dynamic styling - Client-side filtering without new server requests
- Smooth interactions - 60fps pan/zoom on capable hardware
- Vector tiles - Smaller files, dynamic styling
Limitations
- Slower initial load - Heavier JavaScript bundle
- Hardware requirements - Requires WebGL-capable browser
- Accessibility challenges - Canvas renders as opaque to screen readers
- Higher variance - ~17ms standard deviation vs 4.8ms for OpenLayers
Best Use Cases
- Nationwide analytical dashboards
- Large datasets (detention facilities, historical records)
- Dynamic filtering (toggle facility types, time ranges)
- Interactive data visualization
OpenLayers
Architecture
OpenLayers is the most feature-rich option, designed for enterprise-grade GIS operations.
Key Characteristics
| Aspect | Details |
|---|---|
| Bundle Size | Heavy |
| Rendering | Canvas and WebGL |
| License | BSD-2-Clause |
| GIS Features | Complex projections, CAD editing, advanced formats |
Advantages
- Consistent performance - 4.8ms standard deviation
- Extreme scale - 100,000+ lines render twice as fast as competitors
- Full GIS support - Projections, coordinate systems, editing tools
- Format support - Extensive geospatial format compatibility
Limitations
- Steep learning curve - Complex API architecture
- Large bundle - Over-engineered for simple use cases
- Development time - More configuration required
Best Use Cases
- Internal analyst-facing tools
- Complex projection transformations
- Spatial data editing
- Enterprise GIS integration
Performance Benchmarks
Rendering Speed (100,000 lines)
| Library | Speed | Standard Deviation |
|---|---|---|
| OpenLayers | Fastest | 4.8ms |
| Leaflet | Moderate | 6.6ms |
| MapLibre | Slower | 17ms |
Feature Scaling
| Feature Count | Leaflet | MapLibre | OpenLayers |
|---|---|---|---|
| 1,000 | ✅ Smooth | ✅ Smooth | ✅ Smooth |
| 5,000 | ⚠️ Degrading | ✅ Smooth | ✅ Smooth |
| 10,000 | ❌ Sluggish | ✅ Smooth | ✅ Smooth |
| 100,000 | ❌ Unusable | ✅ Smooth | ✅ Excellent |
Accessibility Comparison
| Feature | Leaflet | MapLibre | OpenLayers |
|---|---|---|---|
| Screen readers | ✅ Native DOM elements | ⚠️ Requires ARIA injection | ⚠️ Moderate |
| Keyboard navigation | ✅ Tab through markers | ⚠️ Requires custom handlers | ⚠️ Moderate |
| Focus management | ✅ Native | ❌ Manual implementation | ⚠️ Partial |
Leaflet Accessibility
// Markers are native DOM elements with alt text
L.marker([lat, lng], {
alt: 'Permanent Border Patrol Checkpoint'
}).addTo(map);
MapLibre Accessibility
// Canvas requires explicit ARIA labeling
map.getCanvas().setAttribute('aria-label',
'Interactive map showing immigration checkpoints');
Bundle Size Impact
| Library | Minified + Gzipped | Relative Size |
|---|---|---|
| Leaflet | ~40KB | 1x (baseline) |
| MapLibre GL JS | ~380KB | ~9.5x |
| OpenLayers | ~220KB | ~5.5x |
For mobile users on cellular:
- 40KB loads in ~1 second on 3G
- 380KB loads in ~10 seconds on 3G
Decision Framework
Use Leaflet When:
- [ ] Target audience is mobile-first
- [ ] Network conditions are unreliable (border regions)
- [ ] Feature count is under 5,000
- [ ] Accessibility is critical
- [ ] Quick deployment is needed
- [ ] Simple checkpoint/facility markers
Use MapLibre When:
- [ ] Displaying massive datasets (100,000+ features)
- [ ] Dynamic client-side filtering required
- [ ] Vector tile infrastructure available
- [ ] Users have modern hardware
- [ ] Smooth animations are important
- [ ] Complex data visualization
Use OpenLayers When:
- [ ] Internal analyst tools
- [ ] Complex coordinate projections
- [ ] Spatial data editing workflows
- [ ] Enterprise GIS integration
- [ ] Maximum rendering consistency
- [ ] Advanced format requirements
Integration with 11ty
Leaflet Setup
<!-- In your 11ty template -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script defer src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
MapLibre Setup
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.css" />
<script defer src="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.js"></script>
Lazy Loading (Recommended)
// Load map only when scrolled into view
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
initializeMap();
observer.disconnect();
}
});
});
observer.observe(document.getElementById('map-container'));
Hybrid Approaches
For complex applications, consider hybrid architectures:
| Scenario | Solution |
|---|---|
| Simple overview + detailed drill-down | Leaflet for overview, MapLibre for detail |
| Mobile + desktop | Detect device, load appropriate library |
| Accessibility + performance | Leaflet with accessible overlays, MapLibre for visual layers |
Related Guides
- Tile Servers & Basemaps - Map backgrounds
- Interactive Features - User interactions
- Accessibility - Screen reader support
- Implementation - 11ty integration