perf: optimize homepage and logo images to webp

This commit is contained in:
2026-07-26 10:18:43 +02:00
parent fabc63edf5
commit 789a200595
50 changed files with 126 additions and 29 deletions
@@ -6,7 +6,7 @@ import React, { useRef, useEffect } from 'react'
* - Samples dark pixels → places dots
* - Dots are STATIC until mouse hovers, then they scatter and spring back
*
* For germany: uses /images/germany-outline.png
* For germany: uses /images/germany-outline.webp
* For shield/tools: draws shape on offscreen canvas then samples
*/
export default function DotCloudIcon({ shape = 'germany', size = 140 }) {
@@ -181,7 +181,7 @@ function sampleGermany(size) {
resolve(points)
}
img.onerror = () => { console.error('[DotCloudIcon] Failed to load germany image'); resolve([]) }
img.src = '/images/germany-outline.png'
img.src = '/images/germany-outline.webp'
})
}
@@ -320,6 +320,6 @@ function sampleToolsRightHalf(size) {
resolve(points)
}
img.onerror = () => resolve([])
img.src = '/images/tools.jpg'
img.src = '/images/tools.webp'
})
}
@@ -16,7 +16,7 @@ describe('PhotoBand', () => {
// The CSS animation translates the track by -50%. If the sequence is not
// rendered exactly twice, the loop "jumps" instead of being seamless.
it('renders the image sequence exactly twice for a seamless loop', () => {
const images = ['/a.jpg', '/b.jpg', '/c.jpg']
const images = ['/a.webp', '/b.webp', '/c.webp']
const { container } = render(<PhotoBand images={images} />)
const rendered = [...container.querySelectorAll('.photo-band-track img')].map(img =>
img.getAttribute('src')
@@ -30,7 +30,7 @@ describe('PhotoBand', () => {
it('keeps the duplication invariant for any non-empty image list', () => {
for (const n of [1, 2, 4, 7]) {
const images = Array.from({ length: n }, (_, i) => `/img-${i}.jpg`)
const images = Array.from({ length: n }, (_, i) => `/img-${i}.webp`)
const { container } = render(<PhotoBand images={images} />)
const count = container.querySelectorAll('.photo-band-track img').length
expect(count).toBe(n * 2)
@@ -8,7 +8,7 @@ export default function SEOHead({ title, description, url, image, type = 'websit
const siteTitle = title ? `${title} | Dr. André Knie` : defaultTitle
const siteDesc = description || defaultDescription
const siteUrl = url ? `https://andreknie.de${url}` : "https://andreknie.de"
const siteImage = image || "https://andreknie.de/images/og-image.jpg"
const siteImage = image || "https://andreknie.de/images/og-image.webp"
return (
<Helmet>
+1 -1
View File
@@ -19,7 +19,7 @@ export default function About() {
{/* Profile Card */}
<div className="glass-panel" style={{ padding: '48px', marginBottom: '40px', display: 'flex', gap: '32px', alignItems: 'flex-start', flexWrap: 'wrap' }}>
<img src="/images/andre-knie.png" alt="Dr. André Knie" style={{ width: '140px', height: '140px', borderRadius: '50%', objectFit: 'cover', border: '3px solid rgba(var(--accent-color-rgb), 0.3)' }} />
<img src="/images/andre-knie.webp" alt="Dr. André Knie" style={{ width: '140px', height: '140px', borderRadius: '50%', objectFit: 'cover', border: '3px solid rgba(var(--accent-color-rgb), 0.3)' }} />
<div style={{ flex: 1, minWidth: '250px' }}>
<h2 style={{ marginBottom: '8px' }}>{profile?.name || 'Dr. André Knie'}</h2>
<p style={{ color: 'var(--accent-color)', marginBottom: '16px', fontSize: '0.95rem' }}>
+6 -6
View File
@@ -9,11 +9,11 @@ import PhotoBand from '../components/PhotoBand'
import './Home.css'
const PHOTO_BAND_IMAGES = [
'/images/workshop-1.jpg',
'/images/keynote-1.jpg',
'/images/workshop-2.jpg',
'/images/panel-1.jpg',
'/images/workshop-3.jpg',
'/images/workshop-1.webp',
'/images/keynote-1.webp',
'/images/workshop-2.webp',
'/images/panel-1.webp',
'/images/workshop-3.webp',
]
export default function Home() {
@@ -24,7 +24,7 @@ export default function Home() {
{/* Hero */}
<section className="hero">
<div className="app-container hero-content">
<img src="/images/andre-knie.png" alt="Dr. André Knie" className="hero-photo" />
<img src="/images/andre-knie.webp" alt="Dr. André Knie" className="hero-photo" />
<h1>
{profile?.name || 'Dr. André Knie'}
</h1>
@@ -18,7 +18,7 @@ export default function Speaking() {
{/* Speaker Bio */}
{speaking?.bio && (
<div className="glass-panel" style={{ padding: '32px', maxWidth: '900px', margin: '0 auto 48px', display: 'flex', gap: '28px', alignItems: 'flex-start', flexWrap: 'wrap' }}>
<img src="/images/andre-knie.png" alt="Dr. André Knie" style={{ width: '100px', height: '100px', borderRadius: '50%', objectFit: 'cover', border: '2px solid rgba(var(--accent-color-rgb), 0.3)', flexShrink: 0 }} />
<img src="/images/andre-knie.webp" alt="Dr. André Knie" style={{ width: '100px', height: '100px', borderRadius: '50%', objectFit: 'cover', border: '2px solid rgba(var(--accent-color-rgb), 0.3)', flexShrink: 0 }} />
<div style={{ flex: 1, minWidth: '250px' }}>
<p style={{ color: 'var(--text-secondary)', lineHeight: 1.7, margin: '0 0 16px' }}>{speaking.bio}</p>
{speaking.style && (