2026
This is a modernized rebuild of a project I started years ago and never finished: a 3D choropleth map of the US, built with deck.gl, extruding every county by a COVID-19 statistic and coloring it by a census demographic. The original was abandoned mid-build — the sidebar to actually pick a demographic, a COVID stat, or a date was never wired up, and the app itself was slow enough to be barely usable. This rebuild finishes the feature and fixes the two root causes of that slowness.
The original app fetched Microsoft's live Bing COVID-19 tracker CSV directly in the browser on every page load — which, when I checked it while rebuilding this, had grown to 458MB. On top of that, it joined county geometry to case data with a nested loop comparing every county against every data row, and a county-name matching bug silently broke the join for any multi-word county name. This version fixes both at the root: a one-time offline pipeline downloads and filters that data down to monthly snapshots baked directly into the app (about 8MB total, not 458MB fetched live), and the join runs once, ahead of time, using proper hash-map lookups instead of nested loops.
While rewiring the join between COVID case data and county geometry, I found a bug that had been silently dropping data the whole time: the old code derived a county's name for matching by splitting on the first space, which works for "Cleburne County" but mangles anything with more than one word — "Los Angeles County" became just "Los". Every multi-word county quietly failed to join and never rendered any COVID data at all.
County name matching
// Old code - silently breaks for any multi-word county:
const county = d.AdminRegion2.split(" ")[0].trim();
// "Los Angeles County" -> "Los" (wrong)
// "Miami-Dade County" -> "Miami-Dade" (wrong, no suffix stripped)
// Fixed - strip the known suffix instead of guessing from whitespace:
const COUNTY_SUFFIX_RE =
/\s+(county|parish|borough|census area|municipality|municipio|city and borough|city)$/i;
const county = raw.trim().replace(COUNTY_SUFFIX_RE, "").trim().toLowerCase();
// "Los Angeles County" -> "los angeles" (correct)The other problem was scale: the live Bing COVID-19 dataset this pulls from has grown to 458MB, and the old app fetched the whole thing in the browser on every page load, then matched it against county geometry with a nested loop — comparing every county against every row. Both are fixed at the root rather than optimized in place: a one-time offline script now downloads that 458MB file exactly once, filters it down to one snapshot per month (Jan 2020 – Dec 2022), and bakes a matching key directly onto both the county geometry and the monthly data. The browser only ever fetches the small, pre-joined result — about 8MB total instead of 458MB — and switching months is a single pass over ~3,200 counties using that precomputed key, not a search through millions of rows.
Runtime month switch
// One O(counties) pass per month change - a Map lookup by a key
// baked in ahead of time, not a nested loop over every data row.
function mergeCovidStats(features, monthData) {
return features.map((f) => {
const stats = monthData[f.properties.countyKey];
return {
...f,
properties: {
...f.properties,
covidCases: stats?.[0] ?? 0,
covidDeaths: stats?.[1] ?? 0,
covidRecovered: stats?.[2] ?? 0,
},
};
});
}