Add map-frontend (nginx + MapLibre GL), make pmtiles internal-only

- map-frontend: nginx serves MapLibre GL static app, proxies /tiles/ to pmtiles internally
- pmtiles: remove host port binding (internal to npm-network only), update public-url
- 5 themes: light, dark, grayscale, white, black
This commit is contained in:
2026-03-13 14:14:16 +00:00
parent 662b558d21
commit ef1d136a3e
4 changed files with 147 additions and 3 deletions
+16
View File
@@ -0,0 +1,16 @@
services:
map-frontend:
image: nginx:alpine
container_name: map-frontend
restart: unless-stopped
ports:
- "8087:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./html:/usr/share/nginx/html:ro
networks:
- npm-network
networks:
npm-network:
external: true
+112
View File
@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Maps</title>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
#map { width: 100%; height: 100vh; }
#theme-control {
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
}
#theme-control select {
appearance: none;
background: #fff;
border: 1px solid rgba(0,0,0,0.2);
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0,0,0,0.15);
cursor: pointer;
font-family: system-ui, sans-serif;
font-size: 13px;
padding: 6px 28px 6px 10px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23666'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
}
#theme-control select.dark {
background-color: #1a1a1a;
color: #eee;
border-color: rgba(255,255,255,0.2);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23aaa'/%3E%3C/svg%3E");
}
</style>
</head>
<body>
<div id="map"></div>
<div id="theme-control">
<select id="theme">
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="grayscale">Grayscale</option>
<option value="white">White</option>
<option value="black">Black</option>
</select>
</div>
<script src="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js"></script>
<script type="module">
import { layers, namedFlavor } from 'https://esm.sh/@protomaps/basemaps@4';
const TILESET = 'north-america';
function buildStyle(theme) {
return {
version: 8,
glyphs: 'https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf',
sprite: `https://protomaps.github.io/basemaps-assets/sprites/v4/${theme}`,
sources: {
protomaps: {
type: 'vector',
tiles: [`${window.location.origin}/tiles/${TILESET}/{z}/{x}/{y}.mvt`],
minzoom: 0,
maxzoom: 15,
attribution: '© <a href="https://openstreetmap.org">OpenStreetMap</a>'
}
},
layers: layers('protomaps', namedFlavor(theme), { lang: 'en' })
};
}
const map = new maplibregl.Map({
container: 'map',
style: buildStyle('light'),
center: [-98, 39],
zoom: 4
});
map.addControl(new maplibregl.NavigationControl(), 'top-right');
map.addControl(new maplibregl.ScaleControl(), 'bottom-left');
map.addControl(new maplibregl.FullscreenControl(), 'top-right');
map.addControl(new maplibregl.GeolocateControl({
positionOptions: { enableHighAccuracy: true },
trackUserLocation: true
}), 'top-right');
const themeSelect = document.getElementById('theme');
themeSelect.addEventListener('change', e => {
const theme = e.target.value;
const { lng, lat } = map.getCenter();
const zoom = map.getZoom();
const bearing = map.getBearing();
const pitch = map.getPitch();
themeSelect.className = (theme === 'dark' || theme === 'black') ? 'dark' : '';
map.setStyle(buildStyle(theme));
map.once('styledata', () => {
map.jumpTo({ center: [lng, lat], zoom, bearing, pitch });
});
});
</script>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
server {
listen 80;
# Proxy tile requests to the internal pmtiles server
location /tiles/ {
proxy_pass http://pmtiles:8080/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# Serve the static frontend
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ =404;
}
}
+1 -3
View File
@@ -3,9 +3,7 @@ services:
image: protomaps/go-pmtiles:latest
container_name: pmtiles
restart: unless-stopped
command: serve /data --port=8080 --cors=* --public-url=https://maps.kolpacksoftware.com/
ports:
- "8086:8080"
command: serve /data --port=8080 --cors=* --public-url=https://maps.kolpacksoftware.com/tiles/
volumes:
- /mnt/nas_library/pmtiles/data:/data
networks: