x402-solverdict / tree / tools/gen-og.mjs · raw (this view has old GitHub links rewritten for the mirror; raw is byte-exact)
// Render the static Open Graph images (1200x630 PNG, one per verdict + 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-token
// detail lives in og:title / og:description and the inline SVG card; the PNG shows the verdict color.
//   node tools/gen-og.mjs
import sharp from 'sharp';
import { writeFileSync } from 'node:fs';
const C = { safe: ['#22c55e', 'SAFE'], caution: ['#f59e0b', 'CAUTION'], danger: ['#ef4444', 'DANGER'], generic: ['#a78bfa', 'VERDICT'] };
const shield = (x, y, s, col) => `<g transform="translate(${x},${y}) scale(${s})"><path d="M32 10l18 7v13c0 11-7.6 20-18 24-10.4-4-18-13-18-24V17z" fill="none" stroke="#a78bfa" stroke-width="3.2" stroke-linejoin="round"/><path d="M23 32l6.5 6.5L42 26" fill="none" stroke="${col}" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></g>`;
const F = 'DejaVu Sans, Arial, sans-serif';
const out = {};
for (const [k, [col, word]] 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}"/>
  ${shield(62, 52, 1.7, col)}
  <text x="185" y="125" font-family="${F}" font-size="54" font-weight="700" fill="#e6e9f0">Sol<tspan fill="#a78bfa">Verdict</tspan></text>
  <text x="72" y="215" font-family="${F}" font-size="30" fill="#9aa3b5">Solana token safety check</text>
  ${k === 'generic' ? `<text x="72" y="360" font-family="${F}" font-size="76" font-weight="800" fill="#e6e9f0">SAFE · CAUTION · DANGER</text>` : `<rect x="72" y="262" rx="28" width="${word.length * 78 + 90}" height="150" fill="${col}" fill-opacity="0.14" stroke="${col}" stroke-width="4"/><text x="117" y="375" font-family="${F}" font-size="110" font-weight="800" fill="${col}">${word}</text>`}
  <text x="72" y="490" font-family="${F}" font-size="30" fill="#cbd5e1">Mint &amp; freeze authority · Token-2022 traps · liquidity · holders</text>
  <text x="72" y="560" font-family="${F}" font-size="26" fill="#64748b">api.youraitools.co/solverdict · automated signals, not financial advice</text>
</svg>`;
  const png = await sharp(Buffer.from(svg)).png({ compressionLevel: 9, palette: true, quality: 90 }).toBuffer();
  if (k === 'caution') writeFileSync('/tmp/og-caution.png', png);
  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