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>
The vessel name list runs to tens of thousands of entries and every one
was mounted as a button when the dialog opened, so the Maritime dialog
took several seconds to appear. Because the dialog centres itself in an
effect after the first paint, that delay also showed it flashing at the
top-left before jumping to the middle.
Mount at most 300 rows until the search narrows the list, say how many
are hidden, and centre in a layout effect so the first paint is already
in place.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Carrier icons and labels are built on the main thread from the raw ship
array, separately from the worker that draws every other vessel, so the
Data Filters vessel name / type selection never reached them. Filtering
to yachts left the aircraft carriers on the map.
Move the ship filter predicate into a shared helper used by both the
worker and the carrier builder so all ship sources honour the same
selection.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Each Data Filters section acts on one or more map layers, but the panel
never knew the layer state, so a filter could target a layer that was
switched off and silently do nothing. Four of the five sections build
their option lists from live data, so with the layer off the dialog was
also empty and unsearchable, with no hint why.
Declare the layer keys per section, badge sections whose layers are all
off, and show a banner in the dialog with an ENABLE control per disabled
layer. Enabling from the dialog refetches within a few seconds and the
list fills in place. The empty list now says whether the layer is off,
data is still loading, or the search simply has no match. APPLY stays a
plain apply. Callers that do not pass layer state keep the old behaviour.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>