Files
community-rule/scripts/generate-og-images.mjs
adilalloandCursor 751f2e9343 Resolve share URLs from the instance host and ship 1200×630 Open Graph images.
Staging no longer advertises production canonicals, and Slack/social previews get a default hero card with template and article overrides.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-29 15:41:27 -06:00

71 lines
2.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* Raster 1200×630 Open Graph images from the marketing hero, a templates
* lockup, and each catalog article's section banner.
*
* Run: npm run generate:og-images
*/
import path from "node:path";
import { fileURLToPath } from "node:url";
import sharp from "sharp";
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const PUBLIC = path.join(ROOT, "public");
const OG_WIDTH = 1200;
const OG_HEIGHT = 630;
const CATALOG_SLUGS = [
"resolving-active-conflicts",
"operational-security-mutual-aid",
"making-decisions-without-hierarchy",
"integrating-new-members-without-dilution",
"avoiding-burnout-sustainability-in-the-ruins",
"how-chaos-concentrates-control",
"digital-mediation-and-the-death-of-nuance",
"knowledge-management-and-institutional-amnesia",
];
const TEMPLATES_LOCKUP = `<?xml version="1.0" encoding="UTF-8"?>
<svg width="1200" height="630" viewBox="0 0 1200 630" xmlns="http://www.w3.org/2000/svg">
<rect width="1200" height="630" fill="#000000"/>
<g transform="translate(80 195) scale(8.5)">
<path d="M27.5948 13.9998L0.549194 0.477051L7.31736 13.9998L0.549194 27.5226L27.5948 13.9998ZM14.0855 11.1905C14.6377 11.1938 15.1766 11.3603 15.6343 11.6689C16.092 11.9776 16.4481 12.4146 16.6577 12.925C16.8673 13.4353 16.9211 13.9962 16.8123 14.5371C16.7036 15.0779 16.437 15.5746 16.0463 15.9644C15.6556 16.3543 15.1582 16.6199 14.6166 16.728C14.0751 16.836 13.5137 16.7816 13.0031 16.5715C12.4924 16.3615 12.0554 16.0053 11.747 15.5477C11.4386 15.09 11.2726 14.5515 11.27 13.9998C11.2682 13.6301 11.3398 13.2637 11.4807 12.9218C11.6216 12.58 11.829 12.2694 12.0908 12.0081C12.3527 11.7468 12.6638 11.54 13.0062 11.3997C13.3486 11.2594 13.7154 11.1882 14.0855 11.1905Z" fill="#FFFDD2"/>
</g>
</svg>
`;
async function coverPng(input, output, options = {}) {
await sharp(input, options)
.resize(OG_WIDTH, OG_HEIGHT, { fit: "cover", position: "centre" })
.png()
.toFile(output);
}
async function main() {
const defaultOut = path.join(PUBLIC, "assets/marketing/og-image.png");
const templatesOut = path.join(PUBLIC, "assets/marketing/og-image-templates.png");
await coverPng(
path.join(PUBLIC, "assets/marketing/hero-image.png"),
defaultOut,
);
console.log("Wrote", path.relative(ROOT, defaultOut));
await sharp(Buffer.from(TEMPLATES_LOCKUP))
.png()
.toFile(templatesOut);
console.log("Wrote", path.relative(ROOT, templatesOut));
for (const slug of CATALOG_SLUGS) {
const svgPath = path.join(PUBLIC, "content/blog", `${slug}-section.svg`);
const outPath = path.join(PUBLIC, "content/blog", `${slug}-og.png`);
await coverPng(svgPath, outPath, { density: 300 });
console.log("Wrote", path.relative(ROOT, outPath));
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});