Skip to content

fix(maps): one basemap layer, with a configurable key - #843

Merged
hokiepokedad2 merged 2 commits into
developfrom
fix/842-carto-basemap-key
Aug 27, 2026
Merged

fix(maps): one basemap layer, with a configurable key#843
hokiepokedad2 merged 2 commits into
developfrom
fix/842-carto-basemap-key

Conversation

@hokiepokedad2

Copy link
Copy Markdown
Contributor

Closes #842.

Every map rendered with CARTO's "API KEY REQUIRED" watermark. CARTO requires a key on basemap requests now and watermarks unkeyed ones, but still answers 200 with usable tiles, so nothing logged and no health check noticed. It showed only to whoever was looking at a map.

BasemapService now owns the tile layer, reading basemap_url, basemap_key and basemap_attribution from site settings. Admin settings grows a Maps group for the three, in all eleven locales. Set the key and the watermark goes; leave it blank and you get exactly the maps you have today.

In the built output the CARTO URL now appears once, in one chunk, as ?key={key}.

Three things the issue didn't know

It is five call sites, not four. The issue counted chunks in the deployed image; two of the five share a chunk. Fixing four and stopping would have left the admin geofence submissions map watermarked.

The five had drifted. Three carried no attribution at all, which is a licensing problem independent of the watermark and which centralising fixes on its own. One caps at maxZoom: 18, so createLayer takes an override rather than quietly moving it to 19.

missingKey asks whether the template wants a key, not merely whether one is set. An operator who has pointed basemap_url at a keyless provider is not warned about a key their URL never asked for.

Where the key lives

Admin settings rather than .env, which is a deliberate departure from the issue's suggestion. A CARTO basemap key travels in every tile URL the browser requests, so unlike PORACLE_API_SECRET or DISCORD_BOT_TOKEN it is not a secret and storing it beside them would imply a protection it cannot have. More practically, URL, key and attribution are one unit: an operator able to switch providers in the UI but not supply the matching key has half a control, and the attribution has to change with the provider or it is simply wrong.

Tests

13 for the service, 2 new ones asserting every SETTING_GROUPS label and description resolves in en.json. 1438 passing, clean lint, prettier and production build.

Both new sets were checked by breaking the code first. Dropping encodeURIComponent and loosening missingKey fails two; typoing GROUP_MAPS fails one. That last one closes a real gap — locale-parity compares the eleven locales against each other, so a key missing from all of them is consistent and passes, and the raw key would render as a heading.

Not in scope

All five sites hardcoded light_all, so maps stay light in dark mode. The service is now the right place to fix that, but it needs layer re-creation on theme change across five components and it is not the watermark.

Every map rendered with CARTO's "API KEY REQUIRED" watermark. CARTO requires a
key on basemap requests now and watermarks unkeyed ones, but still answers 200
with usable tiles -- the watermark is drawn into the image, so nothing logs and
no health check notices. It shows only to whoever is looking at the map.

The URL was hardcoded at five call sites, not the four the deployed bundle
suggested: two of them share a chunk. Fixing four and stopping would have left
the admin geofence submissions map watermarked.

BasemapService owns it now, reading basemap_url, basemap_key and
basemap_attribution from site settings. {key} is substituted here rather than
handed to Leaflet, whose template helper throws on a placeholder it has no value
for, and because the encoding is ours to get right. The CARTO parameter is `key`
and not `api_key`; the wrong name also returns 200 and also watermarks, so it is
easy to "fix" this and change nothing.

The five sites had drifted. Three carried no attribution at all, which
centralising fixes on its own, and one caps at maxZoom 18 -- createLayer takes an
override so that one keeps its cap rather than being quietly changed.

missingKey is deliberately narrower than "no key is set": it asks whether the
configured template wants one. An operator who has pointed basemap_url at a
keyless provider is not warned about a key their URL never asked for.

Refs #842.
A 200 response means nothing here -- CARTO returns working tiles without a key
and draws the watermark into the image -- so the only way anyone learns about
this is by looking at a map and recognising what they are seeing. The warning
goes on the admin settings page rather than beside each map, because that is
where the person who can fix it already is.

It reads off BasemapService.missingKey, so it stays silent for an operator whose
configured tile URL wants no key.

Also adds the test that would have caught a typo in this change. A group or
setting whose labelKey is absent from en.json renders the raw key as a heading,
and nothing catches that today: locale-parity compares the eleven locales
against each other, so a key missing from all of them is consistent and passes.

Refs #842.
@github-actions github-actions Bot added the fix label Aug 27, 2026
@hokiepokedad2
hokiepokedad2 merged commit 6d8a2ab into develop Aug 27, 2026
5 checks passed
@hokiepokedad2
hokiepokedad2 deleted the fix/842-carto-basemap-key branch August 27, 2026 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant