Automate OG image generation

This commit is contained in:
2026-03-22 20:59:52 +01:00
parent 3adc61b231
commit a861fa57d2
6 changed files with 128 additions and 4 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
public/repos/ebook-fonts
node_modules
.env

View File

@@ -27,11 +27,12 @@ Fonts are cloned from [ebook-fonts](https://github.com/nicoverbruggen/ebook-font
## OG image
The Open Graph image (`public/assets/favicon/og-image.png`) is a 1200x630 PNG screenshot. To regenerate it from a source image:
The Open Graph image (`public/assets/favicon/og-image.png`) is a 1200x630 PNG screenshot of the app. To regenerate it:
```bash
magick screenshot.png -strip -resize 1200x630 public/assets/favicon/og-image.png
pngquant --quality=65-80 --strip --force --output public/assets/favicon/og-image.png public/assets/favicon/og-image.png
./generate-og-image.sh
```
Requires `imagemagick` and `pngquant` (`brew install pngquant`).
This starts the PHP server, takes a screenshot at 2x (2400x1260) via Playwright, then resizes and optimizes with `magick` and `pngquant`. If the fonts repo isn't cloned yet, it will be cloned automatically.
Requires `imagemagick`, `pngquant` (`brew install pngquant`), and Playwright (`npx playwright install chromium`).

58
generate-og-image.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -euo pipefail
PORT="${PORT:-8888}"
URL="http://localhost:${PORT}"
OUT="public/assets/favicon/og-image.png"
FONTS_DIR="public/repos/ebook-fonts"
cleanup() {
kill "$SERVER_PID" 2>/dev/null || true
}
trap cleanup EXIT
if [ ! -d "$FONTS_DIR" ]; then
echo "Cloning fonts..."
git clone --branch trunk --depth 1 https://github.com/nicoverbruggen/ebook-fonts.git "$FONTS_DIR"
fi
echo "Starting server on ${URL}..."
php -S "0.0.0.0:${PORT}" -t public &
SERVER_PID=$!
sleep 1
echo "Taking screenshot at 2400x1340..."
npx --yes playwright screenshot \
--viewport-size="2400,1340" \
--wait-for-timeout=2000 \
"$URL" "$OUT"
echo "Removing device shadows..."
node -e "
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 2400, height: 1340 } });
await page.goto('$URL');
await page.waitForTimeout(2000);
await page.addStyleTag({ content: '.reader, .reader-screen { box-shadow: none !important; }' });
await page.screenshot({ path: '$OUT' });
await browser.close();
})();
"
echo "Resizing and shifting content up..."
magick "$OUT" -strip -resize 1200x670 -gravity south -crop 1200x630+0+0 +repage "$OUT"
echo "Adding CTA text..."
magick "$OUT" \
-gravity south \
-fill "#6e351b" -draw "rectangle 0,520 1200,630" \
-fill white -font "$FONTS_DIR/fonts/core/Readerly-BoldItalic.ttf" -pointsize 56 \
-gravity south -annotate +0+30 "Explore fonts for digital reading" \
"$OUT"
echo "Optimizing with pngquant..."
pngquant --quality=65-80 --strip --force --output "$OUT" "$OUT"
echo "Done: $OUT ($(ls -lh "$OUT" | awk '{print $5}'))"

59
package-lock.json generated Normal file
View File

@@ -0,0 +1,59 @@
{
"name": "ebook-fonts-showcase",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"devDependencies": {
"playwright": "^1.58.2"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/playwright": {
"version": "1.58.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
"integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.58.2"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.58.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
"integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
}
}
}

5
package.json Normal file
View File

@@ -0,0 +1,5 @@
{
"devDependencies": {
"playwright": "^1.58.2"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 80 KiB