chore: add scripts/generate-og-image.sh to regenerate the OG card
Reproducible ImageMagick script that rebuilds static/og-preview.jpg from the headshot + theme colours (with serif-font fallbacks so it runs on other machines). Exposed as `npm run og:image`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -14,7 +14,8 @@
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
"test:watch": "vitest",
|
||||
"og:image": "./scripts/generate-og-image.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^7.0.0",
|
||||
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Generate the Open Graph / Twitter link-preview card.
|
||||
#
|
||||
# Produces a 1200x630 branded card (the summary_large_image spec) from the
|
||||
# headshot + site theme, written to static/og-preview.jpg. Re-run this whenever
|
||||
# the headshot or branding changes, then redeploy and re-scrape the social
|
||||
# crawlers (see the OG meta tags in src/routes/+layout.svelte).
|
||||
#
|
||||
# Requires ImageMagick 7 (`magick`). Run from anywhere; paths are repo-relative.
|
||||
#
|
||||
# Usage: ./scripts/generate-og-image.sh
|
||||
set -euo pipefail
|
||||
|
||||
# --- locate repo + inputs ---------------------------------------------------
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
SRC_HEADSHOT="static/headshot.jpg"
|
||||
OUT="static/og-preview.jpg"
|
||||
|
||||
if ! command -v magick >/dev/null 2>&1; then
|
||||
echo "error: ImageMagick 7 (magick) not found on PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$SRC_HEADSHOT" ]]; then
|
||||
echo "error: $SRC_HEADSHOT not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- pick a bold + regular serif font (with fallbacks) ----------------------
|
||||
pick_font() {
|
||||
for f in "$@"; do
|
||||
[[ -f "$f" ]] && { echo "$f"; return 0; }
|
||||
done
|
||||
# Last resort: ask fontconfig for any serif.
|
||||
fc-match -f '%{file}' serif 2>/dev/null || true
|
||||
}
|
||||
SERIF_B="$(pick_font \
|
||||
/usr/share/fonts/TTF/DejaVuSerif-Bold.ttf \
|
||||
/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf \
|
||||
/usr/share/fonts/liberation/LiberationSerif-Bold.ttf)"
|
||||
SERIF="$(pick_font \
|
||||
/usr/share/fonts/TTF/DejaVuSerif.ttf \
|
||||
/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf \
|
||||
/usr/share/fonts/liberation/LiberationSerif-Regular.ttf)"
|
||||
: "${SERIF_B:?no bold serif font found}"
|
||||
: "${SERIF:?no serif font found}"
|
||||
|
||||
# --- theme colours (mirror src/lib/theme.ts) --------------------------------
|
||||
GOLD='#ffd700'
|
||||
GOLD_SOFT='#e8c95a'
|
||||
MUTED='#a8a8b8'
|
||||
|
||||
TMP="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
# 1) Dark radial-gradient base (matches the #05050a space theme)
|
||||
magick -size 1200x630 radial-gradient:'#16162c'-'#05050a' "$TMP/base.png"
|
||||
|
||||
# 2) Circular-crop the headshot to 300x300
|
||||
magick "$SRC_HEADSHOT" -resize 300x300^ -gravity center -extent 300x300 \
|
||||
\( -size 300x300 xc:none -fill white -draw "circle 150,150 150,0" \) \
|
||||
-alpha set -compose CopyOpacity -composite "$TMP/headshot_circle.png"
|
||||
|
||||
# 3) Composite headshot (centre 330,315) + gold ring + faint outer ring
|
||||
magick "$TMP/base.png" "$TMP/headshot_circle.png" -geometry +180+165 -compose over -composite \
|
||||
-fill none -stroke "$GOLD" -strokewidth 5 -draw "circle 330,315 330,165" \
|
||||
-stroke "$GOLD" -strokewidth 2 -draw "fill-opacity 0.4 circle 330,315 330,157" \
|
||||
"$TMP/with_headshot.png"
|
||||
|
||||
# 4) Text block (right side) + divider rule
|
||||
magick "$TMP/with_headshot.png" \
|
||||
-font "$SERIF_B" -fill "$GOLD" -pointsize 92 -gravity NorthWest -annotate +540+205 'Kevin Riehl' \
|
||||
-stroke "$GOLD" -strokewidth 2 -draw "line 545,330 980,330" -stroke none \
|
||||
-font "$SERIF" -fill "$GOLD_SOFT" -pointsize 34 -kerning 6 -annotate +547+360 'THE ATLAS OF SKILLS' \
|
||||
-font "$SERIF" -fill "$MUTED" -pointsize 26 -kerning 0 -annotate +547+420 'Interactive skill-tree portfolio' \
|
||||
-fill "$MUTED" -pointsize 26 -annotate +547+455 'Experience · Projects · Skills' \
|
||||
"$TMP/card.png"
|
||||
|
||||
# 5) Flatten to an optimised, progressive JPG
|
||||
magick "$TMP/card.png" -strip -interlace Plane -quality 90 "$OUT"
|
||||
|
||||
echo "wrote $OUT ($(magick identify -format '%wx%h, %B bytes' "$OUT"))"
|
||||
Reference in New Issue
Block a user