import type { APIRoute } from 'astro'; import { resolve } from 'node:path'; import { Resvg } from '@resvg/resvg-js'; import { PAGE_IDS, type PageId } from '@i18n/slugMap'; import { LOCALES, type Locale } from '@i18n/locales'; import { getProfile, getMeta } from '@lib/content'; /* Build-time OpenGraph images (SEO_SPEC §4): one per page per locale, styled in the design system (dark surface, name, role line, trace motif, monogram + page tag). The SVG is hand-built (the design is simple and fully controlled) and rasterised by resvg, which handles the vendored variable TTFs via its own font DB — satori's opentype parser cannot read variable fonts. Fonts read from the project source (cwd = site/ at build). */ const fontDir = resolve(process.cwd(), 'src/assets/og-fonts'); const fontFiles = ['SpaceGrotesk.ttf', 'Inter.ttf', 'JetBrainsMono.ttf'].map((n) => resolve(fontDir, n), ); export function getStaticPaths() { const paths: { params: { image: string }; props: { pageId: PageId; locale: Locale } }[] = []; for (const pageId of PAGE_IDS) { for (const locale of LOCALES) { paths.push({ params: { image: `${pageId}-${locale}` }, props: { pageId, locale } }); } } return paths; } const esc = (s: string) => s.replace(/&/g, '&').replace(//g, '>'); export const GET: APIRoute = ({ props }) => { const { pageId, locale } = props as { pageId: PageId; locale: Locale }; const profile = getProfile(locale); const roleLine = profile.roleLine; const tag = pageId === 'home' ? '' : (getMeta(pageId, locale).title.split(' · ')[0] ?? ''); const tagW = Math.min(tag.length * 15 + 44, 1000); const svg = ` CB cesnimda.co.uk ${esc(profile.name)} ${esc(roleLine)} ${ tag ? ` ${esc(tag)}` : `systems developer · tønsberg, norway` } `; const png = new Resvg(svg, { fitTo: { mode: 'width', value: 1200 }, font: { fontFiles, loadSystemFonts: false, defaultFontFamily: 'Inter' }, }) .render() .asPng(); return new Response(new Uint8Array(png), { headers: { 'Content-Type': 'image/png', 'Cache-Control': 'public, max-age=31536000, immutable', }, }); };