import sharp from 'sharp' import { readdir, stat } from 'fs/promises' import path from 'path' import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const imgDir = path.resolve(__dirname, '../public/images/figma') const SKIP = /\.(svg|webp|gif)$/i const SIZE_LIMITS = { // hero / footer / video-preview — full bleed, keep wide 'hero-bg1.png': { width: 1920 }, 'hero-bg2.png': { width: 1920 }, 'hero-bg-family.png': { width: 1920 }, 'footer-bg.png': { width: 1920 }, 'video-preview.png': { width: 1920 }, // location cards — displayed at ~560px, 2× retina = 1120 'loc-dinopark.jpg': { width: 1200 }, 'loc-divo-lis.png': { width: 1200 }, // gallery tiles — displayed at ~380px, 2× = 760 'gallery-1.png': { width: 800 }, 'gallery-2.png': { width: 800 }, 'gallery-3.png': { width: 800 }, 'gallery-4.png': { width: 800 }, 'gallery-6.png': { width: 800 }, 'gallery-7.png': { width: 800 }, 'gallery-8.png': { width: 800 }, // why-parents side tiles 'why-parents-1.png': { width: 800 }, 'why-parents-2.png': { width: 800 }, 'why-parents-3.png': { width: 800 }, 'why-parents-4.png': { width: 800 }, // news / blog thumbnails 'news-bg1.jpg': { width: 800 }, 'news-bg2.png': { width: 800 }, 'news-bg3.jpg': { width: 800 }, // misc 'review-avatar-bg.jpg': { width: 160 }, 'check-mark.png': { width: 48 }, } const files = await readdir(imgDir) let totalBefore = 0 let totalAfter = 0 for (const file of files) { if (SKIP.test(file)) continue if (file.endsWith('.webp')) continue const src = path.join(imgDir, file) const dst = path.join(imgDir, file.replace(/\.(png|jpg|jpeg)$/i, '.webp')) const srcStat = await stat(src) totalBefore += srcStat.size const limit = SIZE_LIMITS[file] ?? { width: 1920 } try { const info = await sharp(src) .resize({ width: limit.width, withoutEnlargement: true }) .webp({ quality: 82, effort: 4 }) .toFile(dst) totalAfter += info.size const pct = ((1 - info.size / srcStat.size) * 100).toFixed(1) console.log( `✓ ${file} → ${file.replace(/\.(png|jpg|jpeg)$/i, '.webp')} ${(srcStat.size / 1e6).toFixed(1)}MB → ${(info.size / 1e6).toFixed(1)}MB (${pct}% smaller)` ) } catch (err) { console.error(`✗ ${file}: ${err.message}`) } } console.log( `\nTotal: ${(totalBefore / 1e6).toFixed(1)}MB → ${(totalAfter / 1e6).toFixed(1)}MB (${((1 - totalAfter / totalBefore) * 100).toFixed(1)}% reduction)` )