maps update corp

This commit is contained in:
Vincent van der Wal
2026-07-19 23:14:59 +02:00
parent f688b7dbb5
commit faee466286
3 changed files with 86 additions and 3 deletions
+59 -1
View File
@@ -11,7 +11,7 @@ Our objective is to provide a comprehensive, user-friendly weather platform for
- **Framework**: [SvelteKit](https://kit.svelte.dev/)
- **Language**: [TypeScript](https://www.typescriptlang.org/)
- **Data Source**: [Open-Meteo API](https://open-meteo.com/)
- **Visualization**: [Apache Echarts](https://echarts.apache.org)
- **Visualization**: custom canvas charts (`src/lib/charts`)
## Developing
@@ -33,3 +33,61 @@ npm run build
```
You can preview the production build with `npm run preview`.
## Deployment (static hosting)
The build output in `build/` is a fully static site. Two pieces of server
configuration are needed:
### 1. SPA fallback
Pages that are not prerendered (unlisted cities, GPS coordinate routes like
`/weather/week/52.09N5.12E/`) are served by `404.html`, which boots the app
and resolves the location client-side. Configure the server to serve
`404.html` for unknown paths.
### 2. Cross-origin isolation (SharedArrayBuffer for the embedded map)
The `/weather/maps/` page embeds `maps.open-meteo.com`, which uses
`SharedArrayBuffer` for its decoding worker pool. A cross-origin iframe only
gets `SharedArrayBuffer` when the **embedding** page is cross-origin
isolated, so this site must be served with:
```
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```
(The map already serves `Cross-Origin-Resource-Policy: cross-origin` and its
own COOP/COEP, so it is embeddable under these headers. All other assets are
same-origin and the weather APIs are CORS requests, so `require-corp` is safe
here.)
### Example: Caddy
```caddy
ombrella.example.com {
root * /srv/ombrella
file_server
try_files {path} {path}/ /404.html
header {
Cross-Origin-Opener-Policy "same-origin"
Cross-Origin-Embedder-Policy "require-corp"
}
}
```
### Example: nginx
```nginx
server {
server_name ombrella.example.com;
root /srv/ombrella;
error_page 404 /404.html;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
location / {
try_files $uri $uri/ =404;
}
}
```
@@ -135,7 +135,7 @@
<div class="flex h-5 w-5 shrink-0 items-center justify-center">
<svg
class="h-4.5 w-4.5 transition-transform duration-200"
class:rotate-180={!collapsed}
class:rotate-180={collapsed}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
+26 -1
View File
@@ -1,11 +1,32 @@
<script lang="ts">
import { onMount } from 'svelte';
import { storedLocation } from '$lib/stores/settings';
// a #zoom/lat/lng(/bearing/pitch) hash on OUR url is piped through to the
// map, so map positions can be bookmarked/shared via ombrella links
// (the reverse direction is not possible: the iframe is cross-origin, so
// its internal hash changes are unreadable from here)
let hashOverride = $state<string | null>(null);
onMount(() => {
const readHash = () => {
const hash = window.location.hash;
hashOverride = /^#\d+(\.\d+)?\/-?\d+(\.\d+)?\/-?\d+(\.\d+)?/.test(hash) ? hash : null;
};
readHash();
window.addEventListener('hashchange', readHash);
return () => window.removeEventListener('hashchange', readHash);
});
// the embedded map understands maplibre's #zoom/lat/lng hash, so the iframe
// opens focused on the selected location (zoomed out to regional scale);
// picking a new location while on this page recenters the map
const iframeSrc = $derived(
`https://maps.open-meteo.com/#6/${$storedLocation.latitude.toFixed(3)}/${$storedLocation.longitude.toFixed(3)}`
`https://maps.open-meteo.com/${
hashOverride ??
`#6/${$storedLocation.latitude.toFixed(3)}/${$storedLocation.longitude.toFixed(3)}`
}`
);
</script>
@@ -18,11 +39,15 @@
<!-- Full-bleed map: the layout drops its padding for this route. The map
follows our theme through the color-scheme declared on :root/.dark -->
<div class="h-full w-full bg-background">
<!-- allow="cross-origin-isolated" delegates SharedArrayBuffer use to the
map; it only takes effect when this site itself is served with
COOP/COEP headers (see README, Deployment) -->
<iframe
src={iframeSrc}
title="Open-Meteo Interactive Map"
loading="lazy"
allowfullscreen
allow="cross-origin-isolated"
referrerpolicy="no-referrer"
class="block h-full w-full border-0"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"