Bilder selbst hosten: Unsplash-Assets im Docker-Build nach /img/ backen (kein Client-Hotlink, DSGVO); Referenzen Hero/Alarm/Brandmark auf lokale /img/-Pfade; Bildnachweis-Hinweis aktualisiert

This commit is contained in:
2026-06-29 12:15:29 +00:00
parent 568fffdf13
commit 2ffafd4486
7 changed files with 78 additions and 8 deletions
+7
View File
@@ -4,6 +4,13 @@ WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
# Selbst gehostete Bilder: Unsplash-Assets zur Build-Zeit holen und ins eigene Image backen
# (kein Client-Hotlink zu Unsplash -> DSGVO-freundlich). Credits: /bildnachweis
RUN apk add --no-cache curl && mkdir -p public/img \
&& curl -fsSL "https://images.unsplash.com/photo-1649711895336-20ff39db62f8?w=1680&q=72&fm=jpg&fit=crop&auto=format" -o public/img/hero-klima.jpg \
&& curl -fsSL "https://images.unsplash.com/photo-1752218804012-3e7db92274ec?w=1000&q=72&fm=jpg&fit=crop&auto=format" -o public/img/alarm-phone.jpg \
&& curl -fsSL "https://images.unsplash.com/photo-1583444012262-00185bf33cc6?w=160&h=160&q=72&fm=jpg&fit=crop&auto=format" -o public/img/brand-water.jpg \
&& for f in hero-klima alarm-phone brand-water; do test -s "public/img/$f.jpg" || (echo "FEHLT: $f" && exit 1); done
RUN npm run build
# --- Serve stage ---
+46 -1
View File
@@ -12,7 +12,8 @@
"@fontsource/fraunces": "^5.0.0",
"@fontsource/public-sans": "^5.0.0",
"astro": "^5.7.0",
"maplibre-gl": "^4.7.1"
"maplibre-gl": "^4.7.1",
"playwright": "1.48"
}
},
"node_modules/@astrojs/compiler": {
@@ -4185,6 +4186,50 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/playwright": {
"version": "1.48.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz",
"integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==",
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.48.2"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.48.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz",
"integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==",
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/playwright/node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/postcss": {
"version": "8.5.15",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+3 -2
View File
@@ -9,10 +9,11 @@
"preview": "astro preview"
},
"dependencies": {
"astro": "^5.7.0",
"@astrojs/sitemap": "^3.2.0",
"@fontsource/fraunces": "^5.0.0",
"@fontsource/public-sans": "^5.0.0",
"astro": "^5.7.0",
"maplibre-gl": "^4.7.1",
"@astrojs/sitemap": "^3.2.0"
"playwright": "1.48"
}
}
+17
View File
@@ -0,0 +1,17 @@
import { chromium } from 'playwright';
const B='http://l6yk2n8ol78okigxileeyxjt.46.224.49.66.sslip.io/';
const b=await chromium.launch();
for(const [w,h,tag] of [[390,844,'mobile'],[1280,900,'desktop']]){
const p=await b.newPage({viewport:{width:w,height:h},deviceScaleFactor:2});
await p.goto(B,{waitUntil:'networkidle',timeout:30000}).catch(()=>{});
await p.waitForTimeout(2500);
await p.screenshot({path:`/tmp/kf/shot-${tag}.png`});
// check header overflow on mobile
if(tag==='mobile'){
const o=await p.evaluate(()=>{const n=document.querySelector('header nav');return {scrollW:n.scrollWidth,clientW:n.clientWidth,docOverflow:document.documentElement.scrollWidth>window.innerWidth+1};});
console.log('mobile nav scrollW',o.scrollW,'clientW',o.clientW,'pageHorizOverflow',o.docOverflow);
}
await p.close();
}
await b.close();
console.log('done');
+1 -1
View File
@@ -24,7 +24,7 @@ import '../styles/global.css';
.brandmark{border-radius:8px;object-fit:cover;flex:0 0 auto;box-shadow:0 1px 2px rgba(20,40,60,.18)}
</style>
<header class="site"><div class="wrap bar">
<a class="brand" href="/"><img class="brandmark" src="https://images.unsplash.com/photo-1583444012262-00185bf33cc6?w=120&h=120&fit=crop&q=70&auto=format" alt="" width="30" height="30" loading="eager" decoding="async" />Kühl<b>finder</b></a>
<a class="brand" href="/"><img class="brandmark" src="/img/brand-water.jpg" alt="" width="30" height="30" loading="eager" decoding="async" />Kühl<b>finder</b></a>
<nav>
<a href="/geraete">Geräte</a>
<a href="/rechner">Rechner</a>
+1 -1
View File
@@ -22,7 +22,7 @@ const credits = [
</div>
))}
</div>
<p class="note" style="margin-top:1.2rem">Hinweis: Aktuell werden die Bilder über das Unsplash-CDN eingebunden. Für eine vollständig DSGVO-konforme, selbst gehostete Variante können die Dateien lokal unter <code>/public/img/</code> abgelegt und von dort ausgeliefert werden.</p>
<p class="note" style="margin-top:1.2rem">Hinweis: Die Bilder werden <strong>selbst gehostet</strong> (ausgeliefert von dieser Domain unter <code>/img/</code>) es findet kein Hotlink zu Unsplash statt. Die Originale stammen von Unsplash unter der kostenlosen Unsplash-Lizenz.</p>
</section>
</Base>
<style>
+2 -2
View File
@@ -10,8 +10,8 @@ const Pin='<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="c
const Compass='<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg>';
const Bell='<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M6 9a6 6 0 1 1 12 0c0 5 2 6 2 6H4s2-1 2-6Z"/><path d="M10 19a2 2 0 0 0 4 0"/></svg>';
// Unsplash (kostenlose Lizenz) Credits unter /bildnachweis
const IMG_HERO='https://images.unsplash.com/photo-1649711895336-20ff39db62f8?w=1680&q=70&auto=format&fit=crop';
const IMG_PHONE='https://images.unsplash.com/photo-1752218804012-3e7db92274ec?w=1000&q=70&auto=format&fit=crop';
const IMG_HERO='/img/hero-klima.jpg';
const IMG_PHONE='/img/alarm-phone.jpg';
---
<Base title="Kühlfinder Wo gibt es gerade ein Klimagerät? Live-Verfügbarkeit (DE/AT/CH/NL/PL/DK)" description="Live-Bestand von Klimageräten in Baumärkten & Elektromärkten in Deutschland und Nachbarländern, plus Online, Amazon & eBay mit Prognose, Preis-Check gegen Wucher und Alarm.">
<section class="wrap herowrap">