// Generates abstract dark "product shot" SVGs for the portfolio gallery. // Run once: `node scripts/gen-portfolio-art.mjs`. Output -> public/portfolio//*.svg // These are tasteful placeholders; the admin panel can upload real screenshots later. import { mkdirSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; const OUT = join(process.cwd(), 'public', 'portfolio'); // id -> base hue (matches the accent assigned in the dictionary) const PROJECTS = { 'atlas-rag': 199, // electric 'sentinel-agents': 245, // violet 'vertex-vision': 187, // cyan 'mirage-mobile': 292, // magenta 'flux-stream': 158, // emerald 'oracle-forecast': 205, // electric-2 }; const W = 1600; const H = 1000; const defs = (hue, id) => ` ${Array.from({ length: 16 }, (_, i) => ``).join('')} ${Array.from({ length: 10 }, (_, i) => ``).join('')} `; const chrome = (hue, id) => ` `; function dashboard(hue, id) { const bars = Array.from({ length: 9 }, (_, i) => { const bh = 80 + ((i * 53) % 260); return ``; }).join(''); const path = `M 1050 620 ${Array.from({ length: 9 }, (_, i) => `L ${1050 + i * 54} ${620 - Math.sin(i / 1.4) * 120 - i * 6}`).join(' ')}`; return `${defs(hue, id)}${chrome(hue, id)} throughput / day ${bars} latency p95`; } function flow(hue, id) { const node = (x, y, label) => `${label}`; const edge = (x1, y1, x2, y2) => ``; return `${defs(hue, id)}${chrome(hue, id)} ${edge(350, 305, 590, 215)}${edge(350, 305, 590, 405)}${edge(820, 215, 1060, 305)}${edge(820, 405, 1060, 305)}${edge(1290, 305, 1290, 305)} ${node(120, 250, 'ingest')} ${node(590, 160, 'embed')} ${node(590, 350, 'retrieve')} ${node(1060, 250, 'rerank')} ${node(1300, 250, 'generate')} ${Array.from({ length: 6 }, (_, i) => ``).join('')}`; } function mobile(hue, id) { return `${defs(hue, id)} ${Array.from({ length: 4 }, (_, i) => ``).join('')} `; } const SHOTS = [dashboard, flow, mobile]; mkdirSync(OUT, { recursive: true }); for (const [id, hue] of Object.entries(PROJECTS)) { const dir = join(OUT, id); mkdirSync(dir, { recursive: true }); // cover = dashboard variant; gallery = all three variants const files = { 'cover.svg': dashboard(hue, id.replace(/\W/g, '')), '01.svg': dashboard(hue, id.replace(/\W/g, '') + 'a'), '02.svg': flow(hue, id.replace(/\W/g, '') + 'b'), '03.svg': mobile(hue, id.replace(/\W/g, '') + 'c'), }; for (const [name, inner] of Object.entries(files)) { const svg = `${inner}`; writeFileSync(join(dir, name), svg); } console.log('wrote', id); } console.log('done');