#!/usr/bin/env node /** * Generate per-category cover art used as the last-resort image fallback * (baked into /public/covers/*.svg, served statically). * * Design language matches the brand system: ink→brazil gradient (#161614 to * #45060c), maple-500 line art, Source Serif word label. 1200x630 (16:8). * * Usage: node scripts/make-covers.mjs (idempotent — overwrites) */ import { mkdir, writeFile } from 'node:fs/promises'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; const root = join(dirname(fileURLToPath(import.meta.url)), '..'); const outDir = join(root, 'public', 'covers'); const BG = '' + '' + '' + '' + '' + ''; const stroke = 'fill="none" stroke="#f8402f" stroke-opacity="0.38" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"'; const faint = 'fill="none" stroke="#f8402f" stroke-opacity="0.14" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"'; /** Simple geometric motif per category, centred at (880, 300). */ const MOTIFS = { // Parliament Hill: central tower + two flanking towers with connecting wings national: `` + `` + `` + `` + `` + `` + `` + `` + ``, // maple leaf: stem + lobe outline canada: `` + `` + `` + `` + `` + `` + ``, // world globe with meridian (top stories) 'top-stories': `` + `` + `` + `` + `` + `` + `` + ``, }; const LABEL = { national: 'National', canada: 'Canada', 'top-stories': 'Top Stories', }; function cover(category, motif, label) { void category; // contextual only; filename is the real key return ( `` + BG + `` + `` + motif + `${label}` + `MAPLEBRIEF` + `` ); } await mkdir(outDir, { recursive: true }); const covers = { 'top-stories.svg': cover('top-stories', MOTIFS['top-stories'], LABEL['top-stories']), 'national.svg': cover('national', MOTIFS.national, LABEL.national), 'canada.svg': cover('canada', MOTIFS.canada, LABEL.canada), }; for (const [name, svg] of Object.entries(covers)) { await writeFile(join(outDir, name), svg); console.log('wrote', name); }