@@ -473,8 +473,36 @@ function initMap() {
473473 prefetchVisibleClusters ()
474474 })
475475
476- // Add OpenStreetMap tile layer (noWrap prevents world map repeating)
477- L .tileLayer (' https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' , {
476+ // OSM tile servers require a Referer header. Ensure referrer policy allows it.
477+ let metaReferrer = document .querySelector (' meta[name="referrer"]' ) as HTMLMetaElement | null
478+ if (! metaReferrer ) {
479+ metaReferrer = document .createElement (' meta' )
480+ metaReferrer .name = ' referrer'
481+ metaReferrer .content = ' no-referrer-when-downgrade'
482+ document .head .appendChild (metaReferrer )
483+ } else if (metaReferrer .content === ' no-referrer' || metaReferrer .content === ' same-origin' ) {
484+ // Temporarily relax for OSM tiles — restored on unmount
485+ metaReferrer .dataset .originalContent = metaReferrer .content
486+ metaReferrer .content = ' no-referrer-when-downgrade'
487+ }
488+
489+ // Tile layer with retry on 403 (transient referrer issues)
490+ const OsmTileLayer = L .TileLayer .extend ({
491+ createTile(coords : any , done : any ) {
492+ const tile = L .TileLayer .prototype .createTile .call (this , coords , done ) as HTMLImageElement
493+ tile .referrerPolicy = ' no-referrer-when-downgrade'
494+ const originalSrc = tile .src
495+ tile .addEventListener (' error' , () => {
496+ // Retry once after a short delay
497+ if (! tile .dataset .retried ) {
498+ tile .dataset .retried = ' 1'
499+ setTimeout (() => { tile .src = originalSrc }, 500 )
500+ }
501+ }, { once: false })
502+ return tile
503+ }
504+ })
505+ new OsmTileLayer (' https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' , {
478506 attribution: ' © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>' ,
479507 maxZoom: 19 ,
480508 keepBuffer: 2 ,
@@ -780,6 +808,12 @@ onUnmounted(() => {
780808 activeTooltip .remove ()
781809 activeTooltip = null
782810 }
811+ // Restore original referrer policy if we changed it
812+ const metaRef = document .querySelector (' meta[name="referrer"]' ) as HTMLMetaElement | null
813+ if (metaRef ?.dataset .originalContent ) {
814+ metaRef .content = metaRef .dataset .originalContent
815+ delete metaRef .dataset .originalContent
816+ }
783817 // Clean up injected CSS (only if no other PhotoMap instances)
784818 // Note: We leave the CSS in place since it's idempotent and shared
785819 // Removing it could break other instances if multiple PhotoMaps exist
0 commit comments