diff --git a/docs/installation.md b/docs/installation.md index 33a03e4..ace1c2d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -56,6 +56,7 @@ Fœdus reads its configuration from environment variables: | `SPOTIFY_CLIENT_ID` | no | — | Enables the collaborative soundtrack | | `SPOTIFY_CLIENT_SECRET` | no | — | Same as above | | `SPOTIFY_REFRESH_TOKEN` | no | — | Same as above | +| `CARTO_API_KEY` | no | — | Publishable CARTO basemaps API key, appended to map tile requests; without it tiles load keyless | \* The app accepts either the unsuffixed `ADMIN_USER` / `ADMIN_PASSWORD` pair or any number of suffixed `ADMIN_USER1..9` / `ADMIN_PASSWORD1..9` pairs — at least one valid pair must be set, otherwise the process panics at startup rather than expose the dashboard with default credentials. diff --git a/static/parking.js b/static/parking.js index 98d6ce1..f681bd0 100644 --- a/static/parking.js +++ b/static/parking.js @@ -26,6 +26,14 @@ const LEAFLET_JS_URL = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"; let leafletAssetsPromise = null; + function cartoTileURL(style) { + const key = document + .querySelector("meta[name='carto-api-key']") + ?.getAttribute("content"); + const url = `https://{s}.basemaps.cartocdn.com/${style}/{z}/{x}/{y}{r}.png`; + return key ? `${url}?key=${encodeURIComponent(key)}` : url; + } + let map = null; let entries = []; @@ -66,25 +74,19 @@ attributionControl: true, }); - L.tileLayer( - "https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png", - { - attribution: - '© OSM © CARTO', - subdomains: "abcd", - maxZoom: 19, - }, - ).addTo(map); - - L.tileLayer( - "https://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}{r}.png", - { - attribution: "", - subdomains: "abcd", - maxZoom: 19, - pane: "overlayPane", - }, - ).addTo(map); + L.tileLayer(cartoTileURL("light_nolabels"), { + attribution: + '© OSM © CARTO', + subdomains: "abcd", + maxZoom: 19, + }).addTo(map); + + L.tileLayer(cartoTileURL("light_only_labels"), { + attribution: "", + subdomains: "abcd", + maxZoom: 19, + pane: "overlayPane", + }).addTo(map); entries = buildEntries(); map.on("move zoom resize", render); diff --git a/static/places.js b/static/places.js index e903a9d..fe7af30 100644 --- a/static/places.js +++ b/static/places.js @@ -23,6 +23,14 @@ const LEAFLET_JS_URL = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"; let leafletAssetsPromise = null; + function cartoTileURL(style) { + const key = document + .querySelector("meta[name='carto-api-key']") + ?.getAttribute("content"); + const url = `https://{s}.basemaps.cartocdn.com/${style}/{z}/{x}/{y}{r}.png`; + return key ? `${url}?key=${encodeURIComponent(key)}` : url; + } + if (placesSection) initSection(placesSection, "places"); if (honeymoonSection) initSection(honeymoonSection, "honeymoon"); bindModal(); @@ -81,25 +89,19 @@ attributionControl: true, }); - L.tileLayer( - "https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png", - { - attribution: - '© OSM © CARTO', - subdomains: "abcd", - maxZoom: 19, - }, - ).addTo(map); - - L.tileLayer( - "https://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}{r}.png", - { - attribution: "", - subdomains: "abcd", - maxZoom: 19, - pane: "overlayPane", - }, - ).addTo(map); + L.tileLayer(cartoTileURL("light_nolabels"), { + attribution: + '© OSM © CARTO', + subdomains: "abcd", + maxZoom: 19, + }).addTo(map); + + L.tileLayer(cartoTileURL("light_only_labels"), { + attribution: "", + subdomains: "abcd", + maxZoom: 19, + pane: "overlayPane", + }).addTo(map); entries = buildEntries(mode, items, pinsEl, map); diff --git a/templates/layout.templ b/templates/layout.templ index 7452346..ca705f4 100644 --- a/templates/layout.templ +++ b/templates/layout.templ @@ -1,6 +1,7 @@ package templates import ( + "os" "strconv" "strings" @@ -35,6 +36,12 @@ func coordValue(coord float64) string { return strconv.FormatFloat(coord, 'f', -1, 64) } +// cartoAPIKey returns the publishable CARTO basemaps API key from the +// CARTO_API_KEY environment variable, or "" when unset (tiles stay keyless). +func cartoAPIKey() string { + return strings.TrimSpace(os.Getenv("CARTO_API_KEY")) +} + func publicImageURL(mediaID int) string { if mediaID <= 0 { return "" @@ -66,6 +73,9 @@ templ Layout(title string, lang string, t i18n.T, ogMeta OGMeta, includeLeaflet