// Render the static Open Graph images (1200x630 PNG, one per grade + a generic one) into src/og.js.
// Social sites don't render SVG previews and Workers on the free plan can't rasterize per request, so the per-site
// detail lives in og:title / og:description; the PNG shows the grade color.
// node tools/gen-og.mjs
import sharp from 'sharp';
import { writeFileSync } from 'node:fs';
const C = { a: ['#22c55e', 'A'], b: ['#84cc16', 'B'], c: ['#eab308', 'C'], d: ['#f97316', 'D'], f: ['#ef4444', 'F'], generic: ['#38bdf8', null] };
const F = 'DejaVu Sans, Arial, sans-serif';
const logo = (x, y, s) => `<g transform="translate(${x},${y}) scale(${s})"><rect x="14" y="16" width="36" height="28" rx="6" fill="none" stroke="#38bdf8" stroke-width="3.2"/><circle cx="25" cy="29" r="3.2" fill="#38bdf8"/><circle cx="39" cy="29" r="3.2" fill="#38bdf8"/><path d="M32 8v8M22 50h20" stroke="#38bdf8" stroke-width="3.2" stroke-linecap="round"/><path d="M40 44l5 5 9-10" fill="none" stroke="#22c55e" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></g>`;
const out = {};
for (const [k, [col, g]] of Object.entries(C)) {
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630">
<defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#0b1020"/><stop offset="1" stop-color="#111a2e"/></linearGradient></defs>
<rect width="1200" height="630" fill="url(#g)"/><rect x="0" y="0" width="1200" height="12" fill="${col}"/>
${logo(56, 40, 1.9)}
<text x="190" y="125" font-family="${F}" font-size="56" font-weight="700" fill="#e6e9f0">Agent<tspan fill="#38bdf8">Ready</tspan></text>
<text x="72" y="215" font-family="${F}" font-size="32" fill="#9aa3b5">Is this website ready for AI agents?</text>
${g ? `<rect x="72" y="255" rx="28" width="420" height="160" fill="${col}" fill-opacity="0.14" stroke="${col}" stroke-width="4"/><text x="112" y="372" font-family="${F}" font-size="104" font-weight="800" fill="${col}">Grade ${g}</text>` : `<text x="72" y="360" font-family="${F}" font-size="80" font-weight="800" fill="#e6e9f0">Score 0-100 · A-F</text>`}
<text x="72" y="490" font-family="${F}" font-size="28" fill="#cbd5e1">robots.txt AI bots · llms.txt · MCP · OpenAPI · JSON-LD · x402</text>
<text x="72" y="560" font-family="${F}" font-size="26" fill="#64748b">api.youraitools.co/agentready · pay per audit in USDC (x402)</text>
</svg>`;
const png = await sharp(Buffer.from(svg)).png({ compressionLevel: 9, palette: true, quality: 90 }).toBuffer();
out[k] = png.toString('base64');
console.log(k, png.length);
}
writeFileSync(new URL('../src/og.js', import.meta.url), `// Generated by tools/gen-og.mjs: static 1200x630 Open Graph PNGs (base64).\nexport const OG_PNG = ${JSON.stringify(out)};\n`);
agentgate-source: code mirror on Cloudflare Pages. All repos