Skip to main content

R2 CDN — maps.worldmonitor.app

All large static map files are served from Cloudflare R2, not from Vercel. The R2 bucket worldmonitor-maps is fronted by a CF-proxied custom domain:

Why R2 instead of Vercel?

  • Cloudflare bandwidth is free; Vercel charges per GB at scale
  • CF Cache Rules cache /data/, /assets/, /textures/ etc. for 30 days at edge
  • Large files (GeoJSON, PMTiles) don’t bloat the Vercel deployment

Files on R2

Uploading to R2

CORS

R2 does not support wildcard subdomains (https://*.example.com). Each origin must be listed explicitly in the CORS rules. Use r2 bucket cors set or direct curl -X PUT to the R2 API (Wrangler 4.31 may fail with “not well formed”).

Country Geometry Service

File: src/services/country-geometry.ts This service provides all country-level geocoding: point-in-polygon lookups, ISO code resolution, name matching, bounding boxes, and centroids. It loads country boundaries once on first use and indexes them for fast queries.

Data Flow

  1. countries.geojson — base polygons with ISO codes and names, served from /data/ (Vercel)
  2. country-boundary-overrides.geojson — optional higher-resolution polygons from Natural Earth, served from R2 CDN (maps.worldmonitor.app). Features matched by ISO3166-1-Alpha-2 (or ISO_A2) code; matching features replace the base geometry
  3. Base file loads first and the country index is built immediately (service becomes usable). Override file is fetched afterward with a 3-second timeout — failures are silently ignored. Override lookup uses a Map<code, Feature> for O(1) matching

Indexed Data Structures

Key Exports

Name Aliases

Common alternate names are mapped in NAME_ALIASES:

Political Overrides

POLITICAL_OVERRIDES maps sub-national codes to sovereign codes where the app treats them as separate entities (e.g., CN-TW → TW).

Country Boundary Overrides

The override mechanism lets us improve individual country boundaries without replacing the entire countries.geojson. This is the foundation for addressing disputed borders (see #1044).

How It Works

  1. After loading base countries.geojson, the app fetches country-boundary-overrides.geojson from R2 CDN with a 3-second timeout
  2. For each feature in the override file, it matches the country in countries.geojson by ISO Alpha-2 code (using a Map for O(1) lookup)
  3. The override geometry replaces the base geometry (both in the raw GeoJSON used for map rendering and in the indexed point-in-polygon data)
  4. The override file can contain any number of countries — only matching codes are applied

Adding a New Country Override

  1. Source the boundary from Natural Earth 50m Admin 0 (depicts de facto boundaries — actual territorial control — not diplomatic claims)
  2. Extract the country feature by ISO code and save as GeoJSON
  3. Merge into or replace country-boundary-overrides.geojson
  4. Upload to R2:
  5. No code changes needed — the app picks up the new geometry automatically
Example script: scripts/fetch-country-boundary-overrides.mjs downloads the full Natural Earth 50m dataset (~24 MB), extracts country features (currently Pakistan and India), and writes the override file.

Geopolitical Sensitivity

  • Natural Earth shows de facto boundaries (who actually controls the territory), not diplomatic claims
  • This is the same standard used by most mapping platforms
  • When adding overrides for disputed territories, document the source and rationale in the PR description
  • The override system does not add or remove territory — it replaces low-resolution outlines with higher-resolution ones from the same authoritative source

Crimea attribution

The bundled selection geometry represents Crimea as part of Ukraine (UA), as specified in #8609. This is country attribution, not a depiction of territorial control. The correction reuses the exact coordinates in public/data/countries.geojson at commit 42aea73995d19afae2144059afadefdd675f3002. It removes the separate Crimea polygon from Russia and joins its coastline to Ukraine at the existing shared edge, between [33.628517, 46.124935] and [35.001891, 45.729003]. No new coastline coordinates or unrelated boundaries are introduced. The source’s coarse resolution remains, so this is not a coastal-detail upgrade. Regenerate the committed country bounds with node scripts/generate-country-bboxes.cjs after editing the geometry. DeckGLMap uses this geometry for selection and highlighting. GlobeMap uses it for country overlays, including the CII choropleth and Ukraine conflict area. Globe country-click and selection-highlight methods are currently no-ops. The SVG fallback uses the shared coordinate lookup for clicks but separate world topology for its base outlines and has no country selection highlight. Provider tiles and globe imagery are separate assets. A local CARTO basemap check on 2026-09-29 still showed both “Autonomous Republic of Crimea” and “Republic of Crimea” labels under the corrected Ukraine highlight. This geometry change does not change those labels or provider borders. The public boundary override checked on that date contained Pakistan only; future Ukraine or Russia overrides must preserve this attribution.

Fallback Bounds

For regions where full polygon geometry may not be loaded, ME_STRIKE_BOUNDS in country-geometry.ts provides rectangular bounding boxes for Middle Eastern countries. resolveCountryFromBounds() uses these as a fast first pass, falling back to precise point-in-polygon when multiple bounding boxes overlap.

Basemap Tiles

Basemap tile configuration lives in src/config/basemap.ts. See Map Engine for full details on tile providers (PMTiles, OpenFreeMap, CARTO), themes, and fallback behavior. PMTiles are also served from R2 via maps.worldmonitor.app, configured through VITE_PMTILES_URL.

Common Mistakes