From aa4564de03a0e8ca69ade3acbbec998664cf7bc2 Mon Sep 17 00:00:00 2001 From: Marco Kleinert Date: Wed, 17 Jun 2026 08:53:30 +0200 Subject: [PATCH 01/10] feat: optimize PWA icons and events page loading performance --- CHANGELOG.md | 7 ++ events.html | 150 +++++++++++++------------- img/psugh-icon.webp | Bin 0 -> 10998 bytes impressum.html | 2 +- index.html | 2 +- ressourcen/convertfrom-json.html | 2 +- ressourcen/erroractionpreference.html | 4 +- ressourcen/index.html | 2 +- ressourcen/invoke-webrequest.html | 2 +- ressourcen/select-object.html | 2 +- ressourcen/terminating-errors.html | 4 +- ressourcen/throw-write-error.html | 2 +- ressourcen/try-catch.html | 2 +- scripts/_template.html | 2 +- site.webmanifest | 30 ++++-- 15 files changed, 115 insertions(+), 98 deletions(-) create mode 100644 img/psugh-icon.webp diff --git a/CHANGELOG.md b/CHANGELOG.md index 49b3f74..30c7476 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## [Unreleased] +### Added +- Added square modern PWA and apple-touch-icon (`img/psugh-icon.webp`) in WebP format to resolve PWA verification warnings and fix icon squashing on iOS. + +### Changed +- Refactored `events.html` JavaScript to consolidate network fetches, loading all three JSON data files in parallel only once at the page level. +- Combined next meeting details with upcoming events on `events.html` to display the next meeting within the "Kommende Treffen" list. + ## [3.1.0] - 2026-06-16 ### Added - Added June 19th social event ("Bier, Kicker & PowerShell-Talks") with a custom WebP Lego foosball graphic (`img/psugh_social.webp`). diff --git a/events.html b/events.html index 44f98ac..ca41e2a 100644 --- a/events.html +++ b/events.html @@ -24,7 +24,7 @@ - + @@ -176,9 +176,9 @@

Vergangene Treffen

// Calendar functionality class EventCalendar { - constructor() { + constructor(preloadedEvents) { this.currentDate = new Date(); - this.events = []; + this.events = preloadedEvents || []; this.monthNames = [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' @@ -188,70 +188,9 @@

Vergangene Treffen

this.init(); } - async init() { - await this.loadEvents(); + init() { this.render(); this.bindEvents(); - } async loadEvents() { - try { - // Load all three data files - const [currentResponse, pastResponse, upcomingResponse] = await Promise.all([ - fetch('./current-meeting.json'), - fetch('./past-events.json'), - fetch('./upcoming-events.json') - ]); - - const currentData = await currentResponse.json(); - const pastData = await pastResponse.json(); - const upcomingData = await upcomingResponse.json(); - - // Process all events - this.events = []; - - // Add next meeting - if (currentData.nextMeeting) { - // Extract date from "Freitag, den 20.06.2025, ab 18:30h" - const dateMatch = currentData.nextMeeting.date.match(/(\d{2})\.(\d{2})\.(\d{4})/); - if (dateMatch) { - const [, day, month, year] = dateMatch; - this.events.push({ - date: new Date(year, month - 1, day), - title: 'Nächstes Treffen', - type: 'next' - }); - } - } - - // Add past events - if (pastData.pastEvents) { - pastData.pastEvents.forEach(event => { - this.events.push({ - date: new Date(event.date), - title: event.title, - type: 'past' - }); - }); - } - - // Add upcoming events - if (upcomingData.upcomingEvents) { - upcomingData.upcomingEvents.forEach(event => { - // Extract date from "Freitag, den 17.04.2026, ab 18:30h" - const dateMatch = event.date.match(/(\d{2})\.(\d{2})\.(\d{4})/); - if (dateMatch) { - const [, day, month, year] = dateMatch; - this.events.push({ - date: new Date(year, month - 1, day), - title: event.description || 'Kommendes Treffen', - type: 'upcoming' - }); - } - }); - } - - } catch (error) { - console.error('Error loading events:', error); - } } bindEvents() { @@ -327,27 +266,85 @@

Vergangene Treffen

} } } - // Event data loading and rendering - async function loadAndRenderEvents() { + // Consolidated event data loading and initialization + async function initPage() { try { - // Load all three data files - const [pastResponse, upcomingResponse] = await Promise.all([ + // Fetch all three data files in parallel + const [currentResponse, pastResponse, upcomingResponse] = await Promise.all([ + fetch('./current-meeting.json'), fetch('./past-events.json'), fetch('./upcoming-events.json') ]); + const currentData = await currentResponse.json(); const pastData = await pastResponse.json(); const upcomingData = await upcomingResponse.json(); - // Render past events - renderPastEvents(pastData.pastEvents || []); + const currentMeeting = currentData.nextMeeting; + const pastEvents = pastData.pastEvents || []; + const upcomingEvents = upcomingData.upcomingEvents || []; + + // 1. Compile events for the calendar view + const calendarEvents = []; + + if (currentMeeting) { + const dateMatch = currentMeeting.date.match(/(\d{2})\.(\d{2})\.(\d{4})/); + if (dateMatch) { + const [, day, month, year] = dateMatch; + calendarEvents.push({ + date: new Date(year, month - 1, day), + title: 'Nächstes Treffen', + type: 'next' + }); + } + } + + pastEvents.forEach(event => { + calendarEvents.push({ + date: new Date(event.date), + title: event.title, + type: 'past' + }); + }); + + upcomingEvents.forEach(event => { + const dateMatch = event.date.match(/(\d{2})\.(\d{2})\.(\d{4})/); + if (dateMatch) { + const [, day, month, year] = dateMatch; + calendarEvents.push({ + date: new Date(year, month - 1, day), + title: event.description || 'Kommendes Treffen', + type: 'upcoming' + }); + } + }); + + // Initialize calendar with pre-loaded events + new EventCalendar(calendarEvents); + + // 2. Compile upcoming events for card rendering (Next Meeting + Upcoming Events) + const allUpcomingEvents = []; + if (currentMeeting) { + allUpcomingEvents.push({ + date: currentMeeting.date, + dateDisplay: currentMeeting.date, + title: currentMeeting.description || 'Nächstes Treffen', + description: currentMeeting.description, + topics: currentMeeting.topics + }); + } + upcomingEvents.forEach(event => { + allUpcomingEvents.push(event); + }); // Render upcoming events - const upcomingEvents = upcomingData.upcomingEvents || []; - renderUpcomingEvents(upcomingEvents); + renderUpcomingEvents(allUpcomingEvents); + + // Render past events + renderPastEvents(pastEvents); - // Inject Schema.org Event markup for Rich Results - injectEventSchemas(pastData.pastEvents || [], upcomingEvents); + // Inject Schema.org Event markup for SEO + injectEventSchemas(pastEvents, allUpcomingEvents); } catch (error) { console.error('Error loading events:', error); @@ -580,8 +577,7 @@

Vergangene Treffen

} // Initialize immediately; the script is already at the end of the body. - new EventCalendar(); - loadAndRenderEvents(); + initPage(); document.getElementById('footer-year').textContent = new Date().getFullYear(); diff --git a/img/psugh-icon.webp b/img/psugh-icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..68b997f30c3f8f5a970828ed6db2d7143e0cb5e2 GIT binary patch literal 10998 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 - + diff --git a/index.html b/index.html index 06bb7a0..9a2a017 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,7 @@ - + diff --git a/ressourcen/convertfrom-json.html b/ressourcen/convertfrom-json.html index cfad6b1..9d94327 100644 --- a/ressourcen/convertfrom-json.html +++ b/ressourcen/convertfrom-json.html @@ -75,7 +75,7 @@ - + diff --git a/ressourcen/erroractionpreference.html b/ressourcen/erroractionpreference.html index 7558eb9..1de9eaa 100644 --- a/ressourcen/erroractionpreference.html +++ b/ressourcen/erroractionpreference.html @@ -75,7 +75,7 @@ - + @@ -247,4 +247,4 @@

Lokale Abweichung mit "-ErrorAction"

- \ No newline at end of file + diff --git a/ressourcen/index.html b/ressourcen/index.html index fa3ba96..af21139 100644 --- a/ressourcen/index.html +++ b/ressourcen/index.html @@ -82,7 +82,7 @@ - + diff --git a/ressourcen/invoke-webrequest.html b/ressourcen/invoke-webrequest.html index ed815b6..21e4454 100644 --- a/ressourcen/invoke-webrequest.html +++ b/ressourcen/invoke-webrequest.html @@ -75,7 +75,7 @@ - + diff --git a/ressourcen/select-object.html b/ressourcen/select-object.html index f5b3209..652556a 100644 --- a/ressourcen/select-object.html +++ b/ressourcen/select-object.html @@ -77,7 +77,7 @@ - + diff --git a/ressourcen/terminating-errors.html b/ressourcen/terminating-errors.html index 5974c74..bc40d1b 100644 --- a/ressourcen/terminating-errors.html +++ b/ressourcen/terminating-errors.html @@ -79,7 +79,7 @@ - + @@ -252,4 +252,4 @@

Das Verhalten anpassen

- \ No newline at end of file + diff --git a/ressourcen/throw-write-error.html b/ressourcen/throw-write-error.html index 34c9bca..035a1f6 100644 --- a/ressourcen/throw-write-error.html +++ b/ressourcen/throw-write-error.html @@ -79,7 +79,7 @@ - + diff --git a/ressourcen/try-catch.html b/ressourcen/try-catch.html index 3d3b19f..95821ce 100644 --- a/ressourcen/try-catch.html +++ b/ressourcen/try-catch.html @@ -79,7 +79,7 @@ - + diff --git a/scripts/_template.html b/scripts/_template.html index a338fd9..55f6aab 100644 --- a/scripts/_template.html +++ b/scripts/_template.html @@ -90,7 +90,7 @@ - + diff --git a/site.webmanifest b/site.webmanifest index c8d977e..adee5f0 100644 --- a/site.webmanifest +++ b/site.webmanifest @@ -10,14 +10,26 @@ "type": "image/x-icon" }, { - "src": "img/psugh-logo.webp", - "sizes": "200x24", + "src": "img/psugh-icon.webp", + "sizes": "192x192", "type": "image/webp", "purpose": "any" }, { - "src": "img/psugh-logo.webp", - "sizes": "200x24", + "src": "img/psugh-icon.webp", + "sizes": "512x512", + "type": "image/webp", + "purpose": "any" + }, + { + "src": "img/psugh-icon.webp", + "sizes": "192x192", + "type": "image/webp", + "purpose": "maskable" + }, + { + "src": "img/psugh-icon.webp", + "sizes": "512x512", "type": "image/webp", "purpose": "maskable" } @@ -41,8 +53,9 @@ "url": "/#naechstes-treffen", "icons": [ { - "src": "img/psugh-logo.webp", - "sizes": "200x24" + "src": "img/psugh-icon.webp", + "sizes": "192x192", + "type": "image/webp" } ] }, @@ -53,8 +66,9 @@ "url": "/events.html", "icons": [ { - "src": "img/psugh-logo.webp", - "sizes": "200x24" + "src": "img/psugh-icon.webp", + "sizes": "192x192", + "type": "image/webp" } ] } From c22a3f948abba556fd2f084ce815081e92108703 Mon Sep 17 00:00:00 2001 From: Marco Kleinert Date: Wed, 17 Jun 2026 08:57:01 +0200 Subject: [PATCH 02/10] perf: add preload optimization for styles, logo, background, and events JSON --- CHANGELOG.md | 2 ++ events.html | 8 +++++++- impressum.html | 4 ++-- index.html | 3 ++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30c7476..03e4e11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added - Added square modern PWA and apple-touch-icon (`img/psugh-icon.webp`) in WebP format to resolve PWA verification warnings and fix icon squashing on iOS. +- Added preloading for hero background image `img/hintergrund.webp` and minified styles on `index.html`, `events.html`, and `impressum.html` to improve Largest Contentful Paint (LCP) performance. +- Added preloading for JSON data files on `events.html` to load event data as early as possible. ### Changed - Refactored `events.html` JavaScript to consolidate network fetches, loading all three JSON data files in parallel only once at the page level. diff --git a/events.html b/events.html index ca41e2a..5e6ae76 100644 --- a/events.html +++ b/events.html @@ -27,7 +27,13 @@ - + + + + + + +