// Generate the Open Graph share card (1200x630) in the atproto.nl design system. // One-off / manual tooling, not part of `npm run build`. Regenerate with: // node scripts/og-card.mjs // Renders an HTML template with Playwright (already a dev dep via @axe-core/playwright), // then downscales 2x -> 1200x630 with sharp for crisp text. Output: public/brand/og.png. import { chromium } from 'playwright'; import sharp from 'sharp'; import { readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, resolve } from 'node:path'; const here = dirname(fileURLToPath(import.meta.url)); const root = resolve(here, '..'); const W = 1200; const H = 630; // Gruvbox dark tokens (from src/styles/global.css [data-theme='dark']). const PAPER = '#282828'; const INK = '#ebdbb2'; const INKSTRONG = '#fbf1c7'; const ACCENT = '#fe8019'; const RULE = '#504945'; const avatar = readFileSync(resolve(root, 'public/brand/atproto-nl-avatar-1000.png')).toString('base64'); const html = `
//atproto.nl
The AT Protocol community in the Netherlands
Meetups/Members/Tools/Open protocol
`; const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: W, height: H }, deviceScaleFactor: 2 }); await page.setContent(html, { waitUntil: 'networkidle' }); await page.evaluate(() => document.fonts.ready); const buf = await page.screenshot({ type: 'png' }); await browser.close(); await sharp(buf).resize(W, H).png({ compressionLevel: 9 }).toFile(resolve(root, 'public/brand/og.png')); console.log(`Wrote public/brand/og.png (${W}x${H})`);