Maps default to MapLibre (keyless); Mapbox by NUXT_PUBLIC_MAP_PROVIDER=mapbox with a token

This commit is contained in:
doxa-maps 2026-09-28 17:11:58 +00:00
parent fce82c17f8
commit 7114d0a6fd
6 changed files with 24 additions and 7 deletions

View file

@ -90,3 +90,6 @@ MCP_LAYER_PATH=
# MCP server identity advertised in the `initialize` response.
MCP_SERVER_NAME=marketing-rebuild
MCP_SERVER_VERSION=1.0.0
# The map engine for every map: maplibre (keyless, the default) or mapbox (needs NUXT_PUBLIC_MAPBOX_TOKEN).
# NUXT_PUBLIC_MAP_PROVIDER=maplibre

View file

@ -1,4 +1,5 @@
<script setup lang="ts">
import { mapboxTokenIfChosen } from '~/utils/mapProvider'
interface Props {
mapId: string
profileConfig: string
@ -42,8 +43,10 @@ const dxMapsBase = ((runtimeConfig.public as { dxMapsBase?: string }).dxMapsBase
const { locale } = useI18n()
const effectiveConfig = computed(() => {
try {
const cfg = { assetsBase: `${dxMapsBase}/assets`, locale: locale.value, ...JSON.parse(props.profileConfig) }
return JSON.stringify(cfg.tk ? cfg : { ...cfg, provider: 'maplibre' })
// The page's own tk is ignored: the site's provider setting decides (MapLibre by default).
const { tk: _pageToken, ...cfg } = { assetsBase: `${dxMapsBase}/assets`, locale: locale.value, ...JSON.parse(props.profileConfig) }
const tk = mapboxTokenIfChosen(runtimeConfig.public)
return JSON.stringify(tk ? { ...cfg, tk } : { ...cfg, provider: 'maplibre' })
} catch {
return props.profileConfig
}

View file

@ -10,6 +10,7 @@
// element when it scrolls into view and REMOVES it when it scrolls far away. ?only=<bundle>/<profile>
// (comma-separated, or a bundle name) shows just those cards, for a single-plugin check.
import { mapboxTokenIfChosen } from '~/utils/mapProvider'
useHead({ title: 'Embed test', meta: [{ name: 'robots', content: 'noindex' }] })
interface Card {
@ -61,12 +62,12 @@ function loadScript(src: string, integrity: string): Promise<void> {
// so a mounted plugin follows the switcher (profile-config.locale for the maps, the language attribute for
// the shells).
function applyLocale(el: Element, card: Card) {
const token = (runtimeConfig.public as { mapboxToken?: string }).mapboxToken || ''
const token = mapboxTokenIfChosen(runtimeConfig.public)
el.setAttribute('profile-config', JSON.stringify({
profile: card.profile,
assetsBase: `${treeBase()}/assets`,
locale: locale.value,
// with a Mapbox token the maps use it; without one they use the keyless MapLibre engine
// MapLibre by default; Mapbox only when NUXT_PUBLIC_MAP_PROVIDER=mapbox and a token is set
...(token ? { tk: token } : { provider: 'maplibre' })
}))
el.setAttribute('language', locale.value)

View file

@ -13,6 +13,7 @@
// that only exists in the browser, so this keeps it out of SSR and out of Vue's component resolver
// without any nuxt.config change.
import { mapboxTokenIfChosen } from '~/utils/mapProvider'
import { buildUupgListTranslations } from '~/utils/uupgListTranslations'
// ONE scrollbar: no footer here, and the page itself never scrolls; the gallery's own content does.
@ -78,9 +79,8 @@ onMounted(() => {
gallery.setAttribute('tree-base', DX_MAPS_BASE || `${window.location.origin}/dx-maps`)
// The site's language drives the gallery's (and every map's); it follows the language switcher.
gallery.setAttribute('language', locale.value)
// With a Mapbox token configured, the maps use it. Without one (a fresh laptop), they use the
// keyless MapLibre engine, so the page works with no secrets at all.
const token = (runtimeConfig.public as { mapboxToken?: string }).mapboxToken || ''
// MapLibre (keyless) by default; Mapbox only when NUXT_PUBLIC_MAP_PROVIDER=mapbox and a token is set.
const token = mapboxTokenIfChosen(runtimeConfig.public)
if (token) gallery.setAttribute('profile-config', JSON.stringify({ tk: token }))
else gallery.setAttribute('provider', 'maplibre')
host.value?.appendChild(gallery)

8
app/utils/mapProvider.ts Normal file
View file

@ -0,0 +1,8 @@
// The map engine for every dx-maps map on this site. MapLibre (keyless) is the DEFAULT. Set
// NUXT_PUBLIC_MAP_PROVIDER=mapbox to use Mapbox, which also needs NUXT_PUBLIC_MAPBOX_TOKEN; without a token,
// even "mapbox" falls back to MapLibre, so a map always starts.
// Returns the Mapbox token to hand the maps, or '' for MapLibre.
export function mapboxTokenIfChosen(pub: Record<string, unknown>): string {
const provider = String(pub.mapProvider || 'maplibre').toLowerCase()
return provider === 'mapbox' ? String(pub.mapboxToken || '') : ''
}

View file

@ -300,6 +300,8 @@ export default defineNuxtConfig({
siteUrl: process.env.NUXT_PUBLIC_SITE_URL || '',
prayBaseUrl: process.env.NUXT_PUBLIC_PRAY_BASE_URL || 'https://pray.doxa.life',
mapboxToken: process.env.NUXT_PUBLIC_MAPBOX_TOKEN || '',
// The map engine: 'maplibre' (keyless, the default) or 'mapbox' (uses mapboxToken). See app/utils/mapProvider.ts.
mapProvider: process.env.NUXT_PUBLIC_MAP_PROVIDER || 'maplibre',
// Where the Research page loads the dx-maps tree from. This branch defaults to the maps CDN (the
// Plugin Studio container's /cdn). Set NUXT_PUBLIC_DX_MAPS_BASE= (empty) to use this site's own
// /dx-maps/ copy (public/dx-maps) instead. A foreign host must send CORS for the tree.