Use a CARTO API key for map tiles - #902
Merged
Merged
Conversation
CARTO now require an API key on their raster basemaps. Without one the tiles still load, but every one of them is stamped "API KEY REQUIRED". The key is injected into the page at runtime via window.restarters, alongside the config already passed that way, rather than compiled into the bundle. Dockerfile.fly runs the asset build against a stub .env long before the deployed environment's secrets exist, so a VITE_ variable would bake in an empty string and never see the Fly secret. leafletTiles() appends the key when one is present and returns the bare URL when it isn't, so an unconfigured environment degrades to the watermark rather than to a broken map. The standalone #event-map in app.js had its own copy of the tile URL; it now shares the helper. The key is not secret in any meaningful sense - it is served to every visitor in the page - but keeping it in config keeps it out of the repo and lets it differ per environment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Preview: https://restarters-pr-902.fly.dev✅ Ready - restore and migrations succeeded.
|
ngm
approved these changes
Sep 2, 2026
ngm
left a comment
Contributor
There was a problem hiding this comment.
Looks good to me, and works on the preview.
edwh
added a commit
that referenced
this pull request
Sep 2, 2026
#902 keyed the tile URL on the Laravel side, but the client carries its own copy in utils/mapConstants.js - annotated "no API key required", which stopped being true - so every map in the SPA would have come back watermarked once this branch lands. GroupMap, EventVenueMap and GroupForm all read it. useLeafletTiles() appends the key from runtimeConfig.public and returns the bare URL without one, so an unconfigured environment degrades to the watermark rather than a broken map. Runtime config rather than a compiled-in constant for the same reason as the Laravel side: the image is built long before the deployed environment's secrets exist, and Dockerfile.fly already relies on this for apiBase ("runtime-overridable ... so no API URL is baked"). The key falls back to CARTO_API_KEY, which the machine already carries as a Fly secret and Nitro shares the environment with, so no second secret is needed anywhere - production, previews or FLY_PREVIEW_SECRETS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



CARTO now require an API key on their raster basemaps. Without one the tiles still load, but each is stamped API KEY REQUIRED — visible on every group, event and venue map on the site.
Approach
The key is injected at runtime via
window.restarters, next to the config already passed that way, rather than compiled into the bundle.Dockerfile.flyrunsnpm run productionagainst a stub.envlong before the deployed environment's secrets exist, so aVITE_variable would bake in an empty string and never see the Fly secret.leafletTiles()appends the key when present and returns the bare URL when not, so an unconfigured environment degrades to the watermark rather than a broken map. The standalone#event-mapinapp.jshad its own copy of the tile URL and now shares the helper.The key is not secret in any meaningful sense — it is served to every visitor in the page — but keeping it in config keeps it out of the repo and lets it differ per environment.
Secrets
Already staged as
CARTO_API_KEYonrestarters,restarters-devandrestarters-yesterday(staged, so it lands with this deploy — no extra restart).FLY_PREVIEW_SECRETShas been updated so previews get it too.Verification
?key=parameter is read. Retina@2xworks.leafletTiles(); full Jest suite (29) passes;npm run productionbuilds.