/** * Leitet die abgeleiteten Bild-Assets aus den Quelldateien ab. * Einmalig ausfuehren, wenn sich Banner oder Logo aendern: * node scripts/assets.mjs */ import sharp from 'sharp'; import { statSync } from 'node:fs'; const BANNER = 'src/assets/hero-banner.jpg'; const LOGO = 'src/assets/logo-white.png'; const BRAND_BG = { r: 11, g: 16, b: 32, alpha: 1 }; // 1) Club-/Stage-Ausschnitt des Banners: alles links des eingebrannten // "DJ NIZZ"-Schriftzugs (dessen linke Kante liegt bei x = 909) und ohne // die Figur. Dient als Hintergrundebene im Hero, Typo und Figur kommen // als HTML darueber. Breiter schneiden lassen die Geisterbuchstaben // des Schriftzugs im Hintergrund auftauchen. await sharp(BANNER) .extract({ left: 0, top: 0, width: 880, height: 1536 }) .jpeg({ quality: 86, mozjpeg: true }) .toFile('src/assets/hero-club.jpg'); // 2) Open-Graph-Bild 1200x630 aus dem kompletten Banner await sharp(BANNER) .extract({ left: 0, top: 45, width: 2752, height: 1445 }) .resize(1200, 630) .jpeg({ quality: 88, mozjpeg: true }) .toFile('public/og-image.jpg'); // 3) Favicons: das Logo ist weiss auf transparent und waere im hellen // Browser-Tab unsichtbar -> auf Markenblau setzen. const trimmed = await sharp(LOGO) .trim() .resize(880, 880, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } }) .png() .toBuffer(); // sharp wendet resize() intern vor composite() an, unabhaengig von der // Aufrufreihenfolge. Daher erst die 1024er Kachel bauen, dann separat skalieren. const icon = await sharp({ create: { width: 1024, height: 1024, channels: 4, background: BRAND_BG } }) .composite([{ input: trimmed, gravity: 'center' }]) .png() .toBuffer(); for (const size of [32, 180, 192, 512]) { const out = size === 180 ? 'public/apple-touch-icon.png' : `public/favicon-${size}.png`; await sharp(icon).resize(size, size).png({ compressionLevel: 9 }).toFile(out); } const files = [ 'src/assets/hero-banner.jpg', 'src/assets/hero-club.jpg', 'src/assets/nizz-cutout.png', 'src/assets/logo-white.png', 'public/og-image.jpg', 'public/favicon-32.png', 'public/favicon-192.png', 'public/favicon-512.png', 'public/apple-touch-icon.png', ]; for (const f of files) { const m = await sharp(f).metadata(); console.log(f.padEnd(32), `${m.width}x${m.height}`.padEnd(12), `${(statSync(f).size / 1024).toFixed(0)} KB`); }