Skip to content

Commit

Permalink
Automatically generate a new Open Graph image on every build
Browse files Browse the repository at this point in the history
This took some fiddling to get right, and still depends on an arbitrary wait to allow the page to render completely, so will want some proper monitoring when running in the GitHub Actions CD environment.
  • Loading branch information
simonwiles committed Apr 4, 2023
1 parent 7c1796e commit ed6a18a
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 12 deletions.
12 changes: 3 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ dist/
node_modules/

# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*


# environment variables
.env
.env.production

# macOS-specific files
.DS_Store


.vscode/
*.cpuprofile

# assets generated at build-time
assets/
4 changes: 3 additions & 1 deletion astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { defineConfig } from "astro/config";
import svelte from "@astrojs/svelte";
import { astroImageTools } from "astro-imagetools";

import { memewallOgImage } from "./integrations/memewall-og-image.ts";

// https://astro.build/config
export default defineConfig({
site: "https://memes.sucho.org/",
trailingSlash: "always",
integrations: [astroImageTools, svelte()],
integrations: [astroImageTools, svelte(), memewallOgImage()],
vite: {
ssr: { external: ["neat-csv"] },
optimizeDeps: { exclude: ["neat-csv"] },
Expand Down
58 changes: 58 additions & 0 deletions integrations/memewall-og-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { spawn } from "child_process";

import { pEventIterator } from "p-event";
import { chromium } from "playwright";

import type { AstroIntegration } from "astro";

const delay = (milliseconds: number) =>
new Promise((resolve) => {
setTimeout(resolve, milliseconds);
});

const memewallOgImage = (): AstroIntegration => ({
name: "memewall-og-image",
hooks: {
"astro:build:start": async () => {
const astroServerProcess = spawn("pnpm", ["dev"]);
let astroServerUrl: string;

const asyncIterator = pEventIterator(astroServerProcess.stdout, "data");
for await (const chunk of asyncIterator) {
// wait for the Astro dev server to be ready and to report its URL
if (
(astroServerUrl = chunk
.toString()
.match(/http:\/\/[\w\d]+:\d+\//)?.[0])
) {
break;
}
}

console.log(` --> Spawned Astro server listening at ${astroServerUrl}`);

const browser = await chromium.launch({
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-web-security",
],
});

const page = await browser.newPage();
await page.setViewportSize({ width: 1200, height: 630 });
await page.goto(astroServerUrl, { waitUntil: "networkidle" });

// `waitUntil: "networkidle"` seems to be inadequate
console.log(` --> Waiting for the page to render before capturing...`);
await delay(1000);

await page.screenshot({ path: `./assets/open-graph.jpeg` });

await browser.close();
astroServerProcess.kill();
},
},
});

export { memewallOgImage };
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
"dependencies": {
"@floating-ui/dom": "^1.2.1",
"@fontsource/jost": "^4.5.13",
"charts.css": "^0.9.0"
"charts.css": "^0.9.0",
"p-event": "^5.0.1",
"playwright": "^1.31.2"
},
"pnpm": {
"overrides": {
Expand Down
31 changes: 31 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion src/components/Head.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
---
import { execSync } from "node:child_process";
import openGraphImage from "../img/opengraph_image.1200x630.jpeg";
let openGraphImage = "";
try {
({ default: openGraphImage } = await import(
"../../assets/open-graph.jpeg?url"
));
} catch (err) {
if (import.meta.env.PROD) {
// if the open-graph image is not available in PROD, throw an error
// (see integrations/memewall-og-image.ts)
throw err;
}
}
const commit = execSync("git rev-parse --short HEAD").toString().trim();
const datetime = new Date().toISOString();
Expand Down

0 comments on commit ed6a18a

Please sign in to comment.