Files
2026-07-13 12:25:08 +08:00

52 lines
1.8 KiB
JavaScript

/**
* Generates the homepage hero-swarm avatars as static SVG files in
* pages/public/avatars/hero/ so they are served same-origin instead of
* being fetched from api.dicebear.com at runtime (the hero is the LCP
* area — an external origin adds DNS/TLS round trips on mobile).
*
* The output is committed. Re-run after upgrading @dicebear/styles or
* when changing the tiles in AppHeroSwarm.vue:
*
* node scripts/generate-hero-avatars.mjs
*/
import { Avatar, Style } from '@dicebear/core';
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
// Keep in sync with the tiles in theme/components/app/AppHeroSwarm.vue.
const tiles = [
{ styleName: 'lorelei', seed: 'Felix', background: 'ffe4e6', size: 256 },
{ styleName: 'lorelei', seed: 'Aneka', background: 'fef3c7', size: 160 },
{ styleName: 'bottts', seed: 'Pixel', background: 'cffafe', size: 128 },
{ styleName: 'adventurer', seed: 'Milo', background: 'dbeafe', size: 160 },
{ styleName: 'notionists', seed: 'Luna', background: 'dcfce7', size: 128 },
{ styleName: 'thumbs', seed: 'Sage', background: 'ecfccb', size: 128 },
];
const outDir = fileURLToPath(
new URL('../pages/public/avatars/hero/', import.meta.url),
);
await mkdir(outDir, { recursive: true });
for (const tile of tiles) {
const definition = JSON.parse(
await readFile(
new URL(import.meta.resolve(`@dicebear/styles/${tile.styleName}.json`)),
'utf8',
),
);
const avatar = new Avatar(new Style(definition), {
seed: tile.seed,
size: tile.size,
backgroundColor: [tile.background],
});
const fileName = `${tile.styleName}-${tile.seed.toLowerCase()}.svg`;
await writeFile(path.join(outDir, fileName), avatar.toString());
console.log(`✔ ${fileName}`);
}