perf(assets): convert images to webp and check asset paths

Convert 26 PNG/JPG assets to WebP: max 1600 px, q80, diagrams lossless.
src/assets shrinks from 8.3 MB to 4.2 MB.
Use me.jpg for og:image and twitter:image; some crawlers skip WebP.
Add scripts/check-assets.mjs to lint, so a wrong asset path fails lint,
not only at runtime.
This commit is contained in:
lobo committed 2026-10-13 09:13:58 +02:00
1 parent 4e59770e53
commit 2abc7c31e2
62 files changed
+74 -33

No files matched your search

+26 -26
View File
@@ -1,44 +1,44 @@
export class AssetsConstants {
static readonly ME = '/assets/me.webp';
static readonly LOGO = '/assets/logos/logo-wolf.png';
static readonly LOGO = '/assets/logos/logo-wolf.webp';
static readonly FLAG_DE = '/assets/flags/de.svg';
static readonly FLAG_EN = '/assets/flags/gb.svg';
//logos
static readonly CHAMAELEON_LOGO = '/assets/logos/logo_chamaeleon.svg';
static readonly TH_BINGEN_LOGO = '/assets/logos/bingen-logo-white.svg';
static readonly ASSYST_LOGO = '/assets/logos/assyst_gmbh_logo.jpg';
static readonly COLORDIGITAL_LOGO = '/assets/logos/dmixcloud_logo.jpg';
static readonly TERAPORT_LOGO = '/assets/logos/teraport_gmbh_logo.jpg';
static readonly ASSYST_LOGO = '/assets/logos/assyst_gmbh_logo.webp';
static readonly COLORDIGITAL_LOGO = '/assets/logos/dmixcloud_logo.webp';
static readonly TERAPORT_LOGO = '/assets/logos/teraport_gmbh_logo.webp';
static readonly DIPLOMA = '/assets/projects/diploma/Dahm2010-Diplomarbeit.pdf';
//project images
static readonly PLAYGROUND_IMAGES = [
'/assets/projects/playground/1.png'
'/assets/projects/playground/1.webp'
];
static readonly EL_MUCHO_IMAGES = [
'/assets/projects/el-mucho/1.jpg',
'/assets/projects/el-mucho/2.jpg',
'/assets/projects/el-mucho/3.jpg',
'/assets/projects/el-mucho/4.jpg'
'/assets/projects/el-mucho/1.webp',
'/assets/projects/el-mucho/2.webp',
'/assets/projects/el-mucho/3.webp',
'/assets/projects/el-mucho/4.webp'
];
static readonly GAME_JAMS_IMAGES = [
'/assets/projects/game-jams/1.png',
'/assets/projects/game-jams/2.png',
'/assets/projects/game-jams/3.png'
'/assets/projects/game-jams/1.webp',
'/assets/projects/game-jams/2.webp',
'/assets/projects/game-jams/3.webp'
];
static readonly DIPLOMA_IMAGES = [
'/assets/projects/diploma/1.jpg',
'/assets/projects/diploma/2.jpg',
'/assets/projects/diploma/3.jpg',
'/assets/projects/diploma/4.jpg',
'/assets/projects/diploma/5.jpg',
'/assets/projects/diploma/6.jpg'
'/assets/projects/diploma/1.webp',
'/assets/projects/diploma/2.webp',
'/assets/projects/diploma/3.webp',
'/assets/projects/diploma/4.webp',
'/assets/projects/diploma/5.webp',
'/assets/projects/diploma/6.webp'
];
static readonly CLAUDE_BOX_IMAGES = [
@@ -46,16 +46,16 @@ export class AssetsConstants {
];
static readonly TRIBBLE_IMAGES = [
'/assets/projects/tribble-the-homeserver/1.png',
'/assets/projects/tribble-the-homeserver/2.png',
'/assets/projects/tribble-the-homeserver/3.png',
'/assets/projects/tribble-the-homeserver/4.png'
'/assets/projects/tribble-the-homeserver/1.webp',
'/assets/projects/tribble-the-homeserver/2.webp',
'/assets/projects/tribble-the-homeserver/3.webp',
'/assets/projects/tribble-the-homeserver/4.webp'
];
static readonly TBP_IMAGES = [
'/assets/projects/to-be-played/1.png',
'/assets/projects/to-be-played/2.png',
'/assets/projects/to-be-played/3.png',
'/assets/projects/to-be-played/4.png'
'/assets/projects/to-be-played/1.webp',
'/assets/projects/to-be-played/2.webp',
'/assets/projects/to-be-played/3.webp',
'/assets/projects/to-be-played/4.webp'
];
}
+1 -1
View File
@@ -1,6 +1,6 @@
<mat-toolbar class="flex! items-center! p-[clamp(0.5rem,1vw,1rem)]! backdrop-blur-sm! backdrop-saturate-[1.1]! bg-white/80! dark:bg-[#313131]/80! border-b! border-black/8!" color="primary" (keydown)="onKeydown($event)">
<a class="flex items-center gap-[clamp(0.4rem,1vw,0.6rem)] text-inherit no-underline" routerLink="/">
<img class="w-[clamp(36px,10vw,48px)] h-auto rounded-full" src="{{AssetsConstants.LOGO}}" width="117" height="128" alt="" aria-hidden="true" draggable="false"
<img class="w-[clamp(36px,10vw,48px)] h-auto rounded-full" [ngSrc]="AssetsConstants.LOGO" width="117" height="128" loading="eager" alt="" aria-hidden="true" draggable="false"
oncontextmenu="return false;">
<span class="font-semibold tracking-[0.2px] text-[clamp(1rem,3vw,1.2rem)]">{{ 'APP.TITLE' | translate }}</span>
</a>
+2 -1
View File
@@ -5,6 +5,7 @@ import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { MatTooltipModule } from '@angular/material/tooltip';
import { NgOptimizedImage } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { ThemeService } from '../../service/theme.service';
import { LanguageService } from '../../service/language.service';
@@ -17,7 +18,7 @@ import {RouterConstants} from '../../constants/RouterConstants';
imports: [
RouterLink, RouterLinkActive,
MatToolbarModule, MatIconModule, MatButtonModule, MatMenuModule, MatTooltipModule,
TranslatePipe, MatDivider
TranslatePipe, MatDivider, NgOptimizedImage
],
templateUrl: './topbar.component.html',
changeDetection: ChangeDetectionStrategy.Eager,
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 742 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

+2 -2
View File
@@ -19,12 +19,12 @@
<meta property="og:title" content="Andreas Dahm – Playground">
<meta property="og:description" content="Portfolio and interactive playground of Andreas Dahm, senior software developer: algorithm visualizations, GPU simulations and personal projects.">
<meta property="og:url" content="https://andreas-dahm.eu/">
<meta property="og:image" content="https://andreas-dahm.eu/assets/me.webp">
<meta property="og:image" content="https://andreas-dahm.eu/assets/me.jpg">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Andreas Dahm – Playground">
<meta name="twitter:description" content="Portfolio and interactive playground of Andreas Dahm, senior software developer: algorithm visualizations, GPU simulations and personal projects.">
<meta name="twitter:image" content="https://andreas-dahm.eu/assets/me.webp">
<meta name="twitter:image" content="https://andreas-dahm.eu/assets/me.jpg">
<link rel="icon" type="image/x-icon" href="assets/favicon.ico">