# Critical Fixes Implementation Guide
## Overview
This guide explains how to use the new shared architecture to fix all Mapbox globe visualizations. Three critical infrastructure components have been created in the `shared/` directory:
1. **mapbox-config.js** - Centralized token management
2. **data-generator.js** - Unified, realistic data generation
3. **layer-factory.js** - Best-practice layer creation
## The Problem
The original demos (globe_10-13) failed because:
1. ❌ **Invalid tokens**: Placeholder strings like `'pk.eyJ1IjoieW91cnVzZXJuYW1lIiwiYSI6InlvdXJ0b2tlbiJ9.yourtokenstring'`
2. ❌ **Wrong layer types**: Using `fill` layers (requires Polygons) with Point data
3. ❌ **Inconsistent data**: Each demo generated data differently
4. ❌ **No validation**: No error messages when things went wrong
## The Solution
### Architecture Overview
```
mapbox_test/
├── shared/ # NEW: Shared infrastructure
│ ├── mapbox-config.js # Token management & validation
│ ├── data-generator.js # Unified data generation
│ └── layer-factory.js # Best-practice layers
│
├── mapbox_globe_10/ # Polio demo
│ ├── index.html
│ └── src/
│ └── index.js # NOW: Uses shared components
│
├── mapbox_globe_11/ # Measles demo
├── mapbox_globe_12/ # Smallpox demo
└── mapbox_globe_13/ # DTP3 demo
```
## How to Fix Each Demo
### Step 1: Update HTML (index.html)
**Before:**
```html
```
**After:**
```html
```
### Step 2: Update JavaScript (src/index.js)
**Before (BROKEN):**
```javascript
// ❌ Invalid token
mapboxgl.accessToken = 'pk.eyJ1IjoieW91cnVzZXJuYW1lIi...';
// ❌ Wrong layer type for Point data
map.addLayer({
id: 'country-fills',
type: 'fill', // Requires Polygon geometries!
source: 'countries',
paint: { 'fill-color': '#4caf50' }
});
```
**After (WORKING):**
```javascript
import { MAPBOX_CONFIG } from '../shared/mapbox-config.js';
import { generateVaccineData } from '../shared/data-generator.js';
import { LayerFactory } from '../shared/layer-factory.js';
// ✅ Token already applied by HTML import
// ✅ Generate proper Point-based data
const vaccineData = generateVaccineData('polio');
// ✅ Initialize map with validated config
const map = new mapboxgl.Map({
container: 'map',
...MAPBOX_CONFIG.getMapOptions({
center: [20, 20],
zoom: 1.5
})
});
map.on('load', () => {
const factory = new LayerFactory(map);
// ✅ Apply beautiful atmosphere
factory.applyGlobeAtmosphere({ theme: 'medical' });
// ✅ Add data source
map.addSource('vaccine-data', {
type: 'geojson',
data: vaccineData
});
// ✅ Create proper circle layer
const layer = factory.createCircleLayer({
id: 'vaccine-circles',
source: 'vaccine-data',
sizeProperty: 'population',
colorProperty: 'coverage_2020', // For polio
colorScale: 'coverage'
});
map.addLayer(layer);
// ✅ Add hover effects
factory.setupHoverEffects('vaccine-circles');
// ✅ Add legend
factory.addLegend({
title: 'Polio Coverage 2020',
colorScale: 'coverage'
});
});
```
## Complete Example: Fixing globe_10 (Polio)
Here's a complete, working replacement for `mapbox_globe_10/src/index.js`:
```javascript
/**
* Polio Eradication Progress Visualization
* Using shared architecture for reliability
*/
import { MAPBOX_CONFIG } from '../../shared/mapbox-config.js';
import { generateVaccineData } from '../../shared/data-generator.js';
import { LayerFactory, COLOR_SCALES } from '../../shared/layer-factory.js';
// Generate polio data (automatically creates realistic Point geometries)
const polioData = generateVaccineData('polio');
// Initialize map
const map = new mapboxgl.Map({
container: 'map',
...MAPBOX_CONFIG.getMapOptions({
style: 'mapbox://styles/mapbox/dark-v11',
center: [20, 20],
zoom: 1.5
})
});
// Timeline state
let currentYear = 1980;
let isAnimating = false;
let animationInterval = null;
map.on('load', () => {
const factory = new LayerFactory(map);
// Apply medical-themed atmosphere
factory.applyGlobeAtmosphere({ theme: 'medical' });
// Add data source
map.addSource('polio-data', {
type: 'geojson',
data: polioData
});
// Create main circle layer
const layer = factory.createCircleLayer({
id: 'polio-circles',
source: 'polio-data',
sizeProperty: 'population',
colorProperty: 'coverage_1980', // Will update dynamically
colorScale: 'coverage'
});
map.addLayer(layer);
// Setup interactive hover
factory.setupHoverEffects('polio-circles', (feature) => {
const props = feature.properties;
const coverage = props[`coverage_${currentYear}`];
const popup = new mapboxgl.Popup({ offset: 15 })
.setLngLat(feature.geometry.coordinates)
.setHTML(factory.createPopupContent(feature, {
metrics: [
{
label: `Coverage ${currentYear}`,
property: `coverage_${currentYear}`,
format: (v) => `${v}%`
},
{
label: 'Polio Free Since',
property: 'polio_free_year',
format: (v) => v || 'Not certified'
},
{
label: 'Endemic Status',
property: 'endemic',
format: (v) => v ? '🔴 Still endemic' : '✅ Eradicated'
}
]
}))
.addTo(map);
});
// Add legend
factory.addLegend({
title: `Polio Coverage ${currentYear}`,
colorScale: 'coverage',
position: 'bottom-right'
});
// Initialize timeline
updateVisualization();
});
// Update map for current year
function updateVisualization() {
if (!map.isStyleLoaded()) return;
// Update layer color to use current year's data
const colorExpression = [
'interpolate',
['linear'],
['get', `coverage_${currentYear}`],
...COLOR_SCALES.coverage.stops.flatMap((stop, i) => [
stop,
COLOR_SCALES.coverage.colors[i]
])
];
map.setPaintProperty('polio-circles', 'circle-color', colorExpression);
// Update UI
document.getElementById('year-display').textContent = currentYear;
document.getElementById('year-slider').value = currentYear;
// Update statistics (example)
updateStatistics();
}
function updateStatistics() {
const features = map.querySourceFeatures('polio-data');
let totalCoverage = 0;
let certifiedCount = 0;
let endemicCount = 0;
features.forEach(feature => {
const props = feature.properties;
totalCoverage += props[`coverage_${currentYear}`] || 0;
if (props.polio_free_year && currentYear >= props.polio_free_year) {
certifiedCount++;
}
if (props.endemic && currentYear === 2020) {
endemicCount++;
}
});
const avgCoverage = (totalCoverage / features.length).toFixed(1);
document.getElementById('global-coverage').textContent = `${avgCoverage}%`;
document.getElementById('certified-countries').textContent = certifiedCount;
document.getElementById('endemic-countries').textContent = endemicCount;
}
// Timeline controls
document.getElementById('year-slider').addEventListener('input', (e) => {
currentYear = parseInt(e.target.value);
updateVisualization();
});
document.getElementById('play-btn').addEventListener('click', () => {
if (isAnimating) {
clearInterval(animationInterval);
isAnimating = false;
document.getElementById('play-btn').textContent = 'Play';
} else {
isAnimating = true;
document.getElementById('play-btn').textContent = 'Pause';
animationInterval = setInterval(() => {
currentYear++;
if (currentYear > 2020) currentYear = 1980;
updateVisualization();
}, 800);
}
});
document.getElementById('reset-btn').addEventListener('click', () => {
currentYear = 1980;
if (isAnimating) {
clearInterval(animationInterval);
isAnimating = false;
document.getElementById('play-btn').textContent = 'Play';
}
updateVisualization();
});
```
## Data Types for Each Demo
### Polio (globe_10)
```javascript
const polioData = generateVaccineData('polio');
// Properties: coverage_1980, coverage_1990, ..., coverage_2020, polio_free_year, endemic
```
### Measles (globe_11)
```javascript
const measlesData = generateVaccineData('measles');
// Properties: coverage_dose1, coverage_dose2, cases_2023, deaths_2023
```
### Smallpox (globe_12)
```javascript
const smallpoxData = generateVaccineData('smallpox');
// Properties: endemic_1950, endemic_1960, endemic_1970, eradication_year, vaccination_intensity
```
### DTP3 (globe_13)
```javascript
const dtp3Data = generateVaccineData('dtp3');
// Properties: dtp3_coverage_2024, zero_dose_children, under5_mortality_rate, infant_deaths_prevented
```
### HPV (globe_14 - already working!)
```javascript
const hpvData = generateVaccineData('hpv');
// Properties: hpv_coverage_2024, cervical_cancer_incidence, lives_saved_projected, annual_deaths
```
## Color Scales Available
The `LayerFactory` provides these pre-configured color scales:
1. **coverage** - Red → Green (0-100%)
2. **coverageReverse** - Green → Red (inverse)
3. **diverging** - Green ← Gray → Red
4. **purple** - Purple gradient (HPV theme)
5. **blueOrange** - Blue-Orange diverging
Example usage:
```javascript
const layer = factory.createCircleLayer({
id: 'my-layer',
source: 'my-source',
colorScale: 'purple' // Use purple theme
});
```
## Atmosphere Themes
Choose from pre-configured atmosphere themes:
- **default** - Light blue, professional
- **dark** - Deep space, dramatic
- **medical** - Clinical, serious
- **purple** - Health equity theme
```javascript
factory.applyGlobeAtmosphere({ theme: 'medical' });
```
## Validation & Debugging
The new architecture provides automatic validation:
### Token Validation
```javascript
MAPBOX_CONFIG.validateToken();
// Logs: ✅ Mapbox token validated successfully
// OR
// Logs: ❌ MAPBOX TOKEN ERROR: Invalid placeholder token detected!
```
### Data Validation
The data generator ensures:
- ✅ All features are Point geometries
- ✅ Coordinates are [lng, lat] format
- ✅ Realistic values based on income/region
- ✅ Proper property names
### Layer Validation
The layer factory ensures:
- ✅ Circle layers (work with Points)
- ✅ Zoom-responsive sizing
- ✅ Proper color expressions
- ✅ Performance optimizations
## Migration Checklist
For each demo (globe_10, 11, 12, 13):
- [ ] Update `index.html` to import shared config
- [ ] Replace `src/index.js` with new architecture
- [ ] Remove old data file (e.g., `src/data/data.js`)
- [ ] Update imports to use shared modules
- [ ] Test in browser:
- [ ] Globe renders
- [ ] Data appears as circles
- [ ] Hover works
- [ ] Timeline works (if applicable)
- [ ] Colors look correct
- [ ] No console errors
## Benefits of New Architecture
✅ **Reliability**: Valid token guaranteed
✅ **Consistency**: All demos use same patterns
✅ **Maintainability**: Fix bugs in one place
✅ **Performance**: Best-practice layers
✅ **Validation**: Automatic error detection
✅ **Scalability**: Easy to add new demos
## Next Steps
1. Use this architecture to fix globe_10 (Polio)
2. Verify it works perfectly
3. Apply same pattern to globe_11 (Measles)
4. Apply same pattern to globe_12 (Smallpox)
5. Apply same pattern to globe_13 (DTP3)
6. All 5 demos will work beautifully!
## Support
If you encounter issues:
1. **Check browser console** - validation messages appear there
2. **Verify token** - Run `MAPBOX_CONFIG.validateToken()` in console
3. **Check data** - Run `generateVaccineData('polio')` to see generated data
4. **Check layer** - Use Mapbox GL Inspector to see layers
---
**Created**: 2025
**Purpose**: Fix broken Mapbox globe visualizations with shared, validated architecture
**Status**: Ready for implementation