#!/usr/bin/env node /** * Generate OG Image * * Renders the OG image using Playwright with proper Google Fonts. * Counts commands dynamically from the source/ directory and composes * the wordmark alongside a real screenshot of the Chrome extension * detection panel from public/assets/extension-detection.png. * * Usage: bun run og-image */ import { chromium } from 'playwright'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const ROOT_DIR = path.resolve(__dirname, '..'); const OUTPUT_PATH = path.join(ROOT_DIR, 'public', 'og-image.jpg'); const EXTENSION_IMAGE_PATH = path.join( ROOT_DIR, 'public', 'assets', 'extension-detection.png', ); // Count user-invocable, non-deprecated skills from source/skills/ // (In v2.0, commands and skills were unified — every command is a skill.) function getCommandCount() { const skillsDir = path.join(ROOT_DIR, 'source', 'skills'); if (!fs.existsSync(skillsDir)) return 0; let count = 0; for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) { if (!entry.isDirectory()) continue; const skillFile = path.join(skillsDir, entry.name, 'SKILL.md'); if (!fs.existsSync(skillFile)) continue; const content = fs.readFileSync(skillFile, 'utf8'); const fm = content.match(/^---\n([\s\S]*?)\n---/); if (!fm) continue; const frontmatter = fm[1]; const isUserInvocable = /^user-invocable:\s*true\s*$/m.test(frontmatter); const isDeprecated = /^description:\s*["']?DEPRECATED/mi.test(frontmatter); if (isUserInvocable && !isDeprecated) count++; } return count; } // Load extension screenshot as base64 data URL so setContent is self-contained function getExtensionDataUrl() { const buf = fs.readFileSync(EXTENSION_IMAGE_PATH); return `data:image/png;base64,${buf.toString('base64')}`; } async function generateOgImage() { const commands = getCommandCount(); const extensionDataUrl = getExtensionDataUrl(); console.log(`Detected ${commands} command(s)`); const html = `
Impeccable
Design fluency for AI harnesses
${commands} commands · Chrome extension · CLI
impeccable.style
Impeccable Chrome extension detection panel
`; const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 1200, height: 630 }, deviceScaleFactor: 1, }); await page.setContent(html, { waitUntil: 'networkidle' }); // Wait for fonts to load await page.evaluate(() => document.fonts.ready); await page.screenshot({ path: OUTPUT_PATH, type: 'jpeg', quality: 90, }); await browser.close(); const size = (fs.statSync(OUTPUT_PATH).size / 1024).toFixed(0); console.log(`Generated ${OUTPUT_PATH} (${size} KB)`); } generateOgImage().catch((err) => { console.error('Failed to generate OG image:', err); process.exit(1); });