fd2d8a58d9
Each hike now ships two SSR-friendly hero images (light + dark theme), composited at build time from Swisstopo tiles plus an SVG overlay of the trail polyline, start/end markers, and per-photo camera badges. The detail page renders the right variant immediately at first paint, then hands over to live Leaflet without visible jumps. Renderer (scripts/staticHikeMap.ts): - Parallel tile fetcher with on-disk cache (scripts/.cache/swisstopo- tiles/) for re-build idempotency. - `computeStaticMapPose` picks the zoom + centre Leaflet's fitBounds would land on at a reference 1920x640 viewport, so the static frames the full route on every typical desktop hero. - Canvas rendered at 3840x2400 — large enough to fully cover ultrawide / 4K displays at native pixel size, so `object-fit: none` keeps the trail pixel-aligned with Leaflet's tile pane. - SVG overlay: trail in Nord red, start dot Nord green, end dot Nord red, Lucide `camera` icon inside each photo badge. Photo badge fill / border / icon-stroke colours are passed per theme so light and dark variants match the live `.hike-photo-marker .badge` styling exactly (Nord10/Nord8 fill, Nord6/Nord1 border, white/Nord0 icon stroke). Map tiles themselves are identical across themes — no naive invert (it mangles the Pixelkarte palette). - Public photo markers only — private positions are filtered out so they don't leak in the SSR image. Build wiring (scripts/build-hikes.ts): - `processHero` renders both variants in parallel, hashes inputs per theme, skips on cache hit. Output filenames carry the content hash so changes invalidate cleanly via the existing orphan sweep. - `HikeManifestEntry` gains `heroMapUrlLight`, `heroMapUrlDark`, `heroMapZoom`, `heroMapCenter`. Detail page (src/routes/hikes/[slug]/+page.svelte): - Reserves the hero box height up front (kills CLS). - Renders both `<img>` tags; CSS picks the right one via `data-theme` with `prefers-color-scheme` as the fallback. - `object-fit: none; object-position: center` so the image displays at native pixel size, perfectly aligned with Leaflet's tile rendering. - `isolation: isolate` on the hero gives Leaflet's z-index:200+ panes a stacking context so they can't bleed over the sticky nav. HikeMap (src/lib/components/hikes/HikeMap.svelte): - New `initialCenter` / `initialZoom` props — when set, the map opens with `setView` at the static hero's pose instead of `fitBounds`. - New `onReady` callback — fires after the post-fly-to-bounds tile batch finishes loading (or a 350 ms safety timeout), letting the detail page fade the static out onto fully-painted tiles instead of onto a brief grey gap. - Sequence: render static -> Leaflet `setView` to match -> first tile load -> `flyToBounds(track)` to the natural fit -> wait for new tiles -> fade static out.
78 lines
2.9 KiB
JSON
78 lines
2.9 KiB
JSON
{
|
|
"name": "homepage",
|
|
"version": "1.72.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite dev",
|
|
"prebuild": "bash scripts/subset-emoji-font.sh && pnpm exec vite-node scripts/generate-mystery-verses.ts && pnpm exec vite-node scripts/download-models.ts && pnpm exec vite-node scripts/generate-loyalty-cards.ts && pnpm exec vite-node scripts/generate-error-quotes.ts && pnpm exec vite-node scripts/build-hikes.ts",
|
|
"build": "vite build",
|
|
"postbuild": "pnpm exec vite-node scripts/build-error-page.ts",
|
|
"preview": "vite preview",
|
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"test:ui": "vitest --ui",
|
|
"test:coverage": "vitest run --coverage",
|
|
"test:e2e": "playwright test",
|
|
"test:e2e:ui": "playwright test --ui",
|
|
"test:e2e:docker:up": "docker compose -f docker-compose.test.yml up -d",
|
|
"test:e2e:docker:down": "docker compose -f docker-compose.test.yml down -v",
|
|
"test:e2e:docker": "docker compose -f docker-compose.test.yml up -d && playwright test; docker compose -f docker-compose.test.yml down -v",
|
|
"test:e2e:docker:run": "docker run --rm --network host -v $(pwd):/app -w /app -e CI=true mcr.microsoft.com/playwright:v1.56.1-noble /bin/bash -c 'npm install -g pnpm@9.0.0 && pnpm install --frozen-lockfile && pnpm run build && pnpm exec playwright test --project=chromium'",
|
|
"deploy": "bash scripts/deploy.sh",
|
|
"deploy:dry": "bash scripts/deploy.sh --dry-run",
|
|
"tauri": "tauri"
|
|
},
|
|
"packageManager": "pnpm@9.0.0",
|
|
"devDependencies": {
|
|
"@playwright/test": "1.56.1",
|
|
"@sveltejs/adapter-auto": "^7.0.1",
|
|
"@sveltejs/kit": "^2.56.1",
|
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
"@tauri-apps/cli": "^2.10.1",
|
|
"@testing-library/jest-dom": "^6.9.1",
|
|
"@testing-library/svelte": "^5.3.1",
|
|
"@types/leaflet": "^1.9.21",
|
|
"@types/node": "^22.12.0",
|
|
"@types/node-cron": "^3.0.11",
|
|
"@vitest/ui": "^4.1.2",
|
|
"bwip-js": "^4.10.1",
|
|
"jsdom": "^27.2.0",
|
|
"mdsvex": "^0.12.7",
|
|
"svelte": "^5.55.1",
|
|
"svelte-check": "^4.4.6",
|
|
"tslib": "^2.8.1",
|
|
"typescript": "^6.0.2",
|
|
"vite": "^8.0.4",
|
|
"vite-node": "^6.0.0",
|
|
"vitest": "^4.1.2"
|
|
},
|
|
"dependencies": {
|
|
"@auth/sveltekit": "^1.11.1",
|
|
"@huggingface/transformers": "^4.0.1",
|
|
"@lucide/svelte": "^1.7.0",
|
|
"@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
|
|
"@sveltejs/adapter-node": "^5.5.4",
|
|
"@tauri-apps/plugin-geolocation": "^2.3.2",
|
|
"barcode-detector": "^3.1.2",
|
|
"chart.js": "^4.5.1",
|
|
"chartjs-adapter-date-fns": "^3.0.0",
|
|
"date-fns": "^4.1.0",
|
|
"exifr": "^7.1.3",
|
|
"file-type": "^19.0.0",
|
|
"leaflet": "^1.9.4",
|
|
"mongoose": "^9.4.1",
|
|
"node-cron": "^4.2.1",
|
|
"romcal": "github:AlexBocken/romcal#dev",
|
|
"sharp": "^0.34.5",
|
|
"web-haptics": "^0.0.6"
|
|
},
|
|
"pnpm": {
|
|
"onlyBuiltDependencies": [
|
|
"esbuild"
|
|
]
|
|
}
|
|
}
|