Add runtime CARTO_API_KEY for basemap tiles

CARTO now requires an API key for its basemap tiles; without one every
tile in the DEFAULT dark/light map carries an "API KEY REQUIRED"
watermark. The tile URLs were hardcoded in mapStyles.ts with no way to
supply a key, and because the frontend ships as a prebuilt image a
NEXT_PUBLIC_ variable would be baked in empty for every Docker user.

- New frontend-local route GET /api/basemap-config reads CARTO_API_KEY
  from the frontend container's environment at request time (same
  pattern as BACKEND_URL), so no image rebuild is needed.
- useBasemapConfig() fetches it once per page load; MaplibreViewer
  builds the MapLibre style from it via buildBasemapStyle(theme, key)
  and defers the map's first style load until the config has settled,
  avoiding a burst of unkeyed tile requests followed by a style swap.
- Tile URLs move to CARTO's documented rastertiles/ path with ?key=
  appended when configured. Unkeyed URLs serve byte-identical tiles to
  the old path, so deployments without a key behave exactly as before.
- CARTO_API_KEY wired through docker-compose.yml and documented in
  .env.example, README (data source table + frontend env table) and
  docs/OUTBOUND_DATA.md.
- Tests cover the route (unset / set / trimmed) and the style builder.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
C3B2W23
2026-09-13 14:54:01 -07:00
co-authored by Claude Fable 5.1
parent a5fb1c392e
commit 8f169f1ecc
9 changed files with 234 additions and 43 deletions
+2 -1
View File
@@ -666,7 +666,7 @@ ShadowBroker v0.9.7 is composed of three vertically-stacked planes — the **Ope
| [Wikidata SPARQL](https://query.wikidata.org) | Head of state data | On-demand (cached 24h) | No |
| [Wikipedia API](https://en.wikipedia.org/api) | Location summaries & aircraft images | On-demand (cached) | No |
| [OSM Nominatim](https://nominatim.openstreetmap.org) | Place name geocoding (LOCATE bar) | On-demand | No |
| [CARTO Basemaps](https://carto.com) | Dark map tiles | Continuous | No |
| [CARTO Basemaps](https://carto.com) | Dark/light map tiles | Continuous | **Yes** (free, `CARTO_API_KEY`) |
**Outbound privacy & audit (#348–#366):** Each self-hosted install uses its own backend IP and per-install User-Agent handle. See [docs/OUTBOUND_DATA.md](docs/OUTBOUND_DATA.md) for what contacts third parties, opt-in/env controls, and accepted tradeoffs (CCTV Referer, basemap CDN, LiveUAMap, etc.).
@@ -1173,6 +1173,7 @@ Then confirm authenticated `GET /api/wormhole/status` or `GET /api/settings/worm
|---|---|---|
| `BACKEND_URL` | `environment` in `docker-compose.yml`, or shell env | URL the Next.js server uses to proxy API calls to the backend. Defaults to `http://backend:8000`. **Runtime variable — no rebuild needed.** |
| `BACKEND_PORT` | repo-root `.env` or shell env before `docker compose up` | Host port used to expose the backend API for local diagnostics. Defaults to `8000`; set `BACKEND_PORT=8001` if port 8000 is already in use. Does not change Docker-internal `BACKEND_URL`. |
| `CARTO_API_KEY` | repo-root `.env` (passed to the frontend container by `docker-compose.yml`), or shell env | API key for the CARTO basemap tiles behind the DEFAULT dark/light map. CARTO now requires one; without it tiles still load but carry an "API KEY REQUIRED" watermark. Free at [carto.com/basemaps/apikey](https://carto.com/basemaps/apikey) (no account needed, 5M tiles/month). Served to the browser by the frontend-local `/api/basemap-config` route. **Runtime variable — no rebuild needed.** |
**How it works:** The frontend proxies all `/api/*` requests through the Next.js server to `BACKEND_URL` using Docker's internal networking. Browsers only talk to port 3000; the backend host port is only for local diagnostics. For local dev without Docker, `BACKEND_URL` defaults to `http://localhost:8000`.