Skip to content

docs(og): add 1920×1080 cover art set + wire og-01 as og:image#132

Merged
youtalk merged 4 commits intomainfrom
docs/og-cover-art
Apr 27, 2026
Merged

docs(og): add 1920×1080 cover art set + wire og-01 as og:image#132
youtalk merged 4 commits intomainfrom
docs/og-cover-art

Conversation

@youtalk
Copy link
Copy Markdown
Owner

@youtalk youtalk commented Apr 27, 2026

Summary

  • Adds seven 1920×1080 cover compositions under docs/img/og/, rendered from a shared gallery page (docs/og.html) so they pull from the landing page's design system (Fraunces × Spectral × JetBrains Mono · paper / ink / vermilion / mora-orange / mora-teal · halftone, washi, phoneme bars, chop seal). Use as the site OG image, YouTube thumbnails, or social-card source material.
  • Wires og-01.png into docs/index.html as og:image / twitter:image (with width / height / alt) and surfaces it as a hero image at the top of README.md. The chop-seal mark is the actual AppIcon.appiconset/AppIcon.png, not arbitrary kanji.
  • Ships tools/og/render-og.sh — a headless-Chrome renderer that works around a known headless quirk where Chrome reserves ~90px of phantom browser chrome at the bottom of every screenshot.

The compositions

File Concept
og-01.png Overture · paper editorial cover, big Mora. wordmark, three yokai cards, AppIcon chop
og-01-dyslexic.png Same as og-01 but the wordmark is set in OpenDyslexic — the dyslexia-friendly typeface this product is built around
og-02.png Substitution slab · dark ink with massive phoneme math (b ← v, r ← l, s ← th)
og-03.png The Numbers · 5 days / 100+ PRs / 25.84 MB / 0 cloud calls
og-04.png Pull quote · "I built Mora for one kid I love." with AppIcon chop
og-05.png Yokai triumvirate · three rotated mentor cards on washi
og-06.png Terminal · dev / code aesthetic with live phoneme posterior bars

Why a render script (and not just hand-edited PNGs)

Headless Chrome's --screenshot reserves ~90px of phantom browser chrome at the bottom of every capture, leaking the gallery body background into the rendered PNG. The script renders at 1920×1170 and crops the top 1920×1080 via Pillow so each board ends exactly at its own background (paper / ink / washi).

Re-render any subset:

tools/og/render-og.sh                   # all seven
tools/og/render-og.sh 01 04             # just those
tools/og/render-og.sh 01-dyslexic       # the OpenDyslexic title variant

A note on the GitHub repo's social preview

GitHub's per-repo "social preview" image is a Settings UI feature, not a file in the repo — once this PR lands, upload docs/img/og/og-01.png (or og-01-dyslexic.png) at https://github.com/youtalk/mora/settings under General → Social preview.

Test plan

  • docs/og.html opens in a browser and renders the gallery (all seven boards visible at scale).
  • Clicking "Open native" on a board switches to a 1920×1080 fullscreen view with no body-bg leak.
  • tools/og/render-og.sh re-generates all seven PNGs without errors and the bottom row of each PNG shows that board's intended background, not #1a1a1a.
  • Run an OG-card preview tool (e.g. opengraph.xyz) against https://www.youtalk.jp/mora once the change is deployed and confirm og:image resolves to og-01.png at 1920×1080.

🤖 Generated with Claude Code

Add seven OG / YouTube-thumbnail compositions under `docs/img/og/`,
all rendered from a single gallery page (`docs/og.html`) so they share
the landing page's design system (Fraunces × Spectral × JetBrains Mono ·
paper / ink / vermilion / mora-orange / mora-teal · halftone, washi,
phoneme bars, chop seal):

- og-01 — Overture (paper editorial cover, AppIcon chop, yokai stack)
- og-02 — Substitution slab (dark phoneme math: b←v, r←l, s←th)
- og-03 — The Numbers (5 / 100+ / 25.84 / 0)
- og-04 — Pull quote ("I built Mora for one kid I love." + AppIcon chop)
- og-05 — Yokai triumvirate (three mentor cards on washi)
- og-06 — Terminal (dev/code aesthetic with live phoneme posterior)
- og-01-dyslexic — same as og-01 but the "Mora." wordmark is set in
  OpenDyslexic, the dyslexia-friendly typeface this product is built for

Wire og-01.png into the landing page's `og:image` / `twitter:image`
(with width/height/alt) and surface it as a hero image at the top of
the README. The chop-seal mark on og-01 / og-04 is the actual
`Mora/Assets.xcassets/AppIcon.appiconset/AppIcon.png`, not arbitrary
kanji.

Ship a `tools/og/render-og.sh` headless-Chrome renderer. It works
around a headless quirk where Chrome reserves ~90px of phantom browser
chrome at the bottom of every screenshot — render at 1920×1170 and
crop the top 1920×1080 via Pillow so the rendered PNGs end exactly at
their natural board background instead of leaking the body bg.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 27, 2026 19:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a curated set of 1920×1080 OpenGraph/social cover images to the docs site, provides a local gallery for viewing them at scale, and wires the primary cover image into the site’s OG/Twitter metadata and README.

Changes:

  • Add docs/og.html gallery page that renders seven 16:9 cover compositions using the site’s design system.
  • Add tools/og/render-og.sh to headlessly render/crop the gallery boards into docs/img/og/*.png.
  • Update docs/index.html OG/Twitter meta tags and add a hero image to README.md.

Reviewed changes

Copilot reviewed 4 out of 12 changed files in this pull request and generated 5 comments.

File Description
tools/og/render-og.sh New headless Chrome renderer + crop step for generating 1920×1080 OG PNG assets.
docs/og.html New gallery page containing the seven OG cover compositions and “native” anchors for rendering.
docs/index.html Switch og:image/twitter:image to img/og/og-01.png and add width/height/alt metadata.
README.md Surface og-01.png as a top-of-README hero image linking to the docs landing page.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/og.html
<header class="page-header">
<h1>Mora · 16:9 Cover Art <em>Gallery</em></h1>
<p>
Six 1920×1080 thumbnails for OG image / YouTube. Click <code>Open native</code> on any board to view it full-size, then export with Chrome DevTools → <code>Capture node screenshot</code>, or run the headless render script: <code>tools/og/render-og.sh</code>.
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header copy says “Six 1920×1080 thumbnails…”, but this page now includes seven boards (Patterns 01–07, including the OpenDyslexic variant). Update the count so the page description matches what’s actually rendered.

Suggested change
Six 1920×1080 thumbnails for OG image / YouTube. Click <code>Open native</code> on any board to view it full-size, then export with Chrome DevTools → <code>Capture node screenshot</code>, or run the headless render script: <code>tools/og/render-og.sh</code>.
Seven 1920×1080 thumbnails for OG image / YouTube. Click <code>Open native</code> on any board to view it full-size, then export with Chrome DevTools → <code>Capture node screenshot</code>, or run the headless render script: <code>tools/og/render-og.sh</code>.

Copilot uses AI. Check for mistakes.
Comment thread tools/og/render-og.sh
Comment on lines +5 to +7
# :has(.thumb:target) to swap into a fullscreen, native-size view of just
# that board, which lets headless Chrome capture a pixel-perfect 1920×1080
# screenshot per pattern.
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script header comment says the gallery uses :has(.thumb:target) to enter the native/fullscreen view, but docs/og.html uses .thumb:target selectors (no :has). Please update the comment to match the actual mechanism so future changes don’t get made based on incorrect CSS assumptions.

Suggested change
# :has(.thumb:target) to swap into a fullscreen, native-size view of just
# that board, which lets headless Chrome capture a pixel-perfect 1920×1080
# screenshot per pattern.
# .thumb:target selectors to swap into a fullscreen, native-size view of
# just that board, which lets headless Chrome capture a pixel-perfect
# 1920×1080 screenshot per pattern.

Copilot uses AI. Check for mistakes.
Comment thread tools/og/render-og.sh
# screenshot per pattern.
#
# Usage: tools/og/render-og.sh [pattern_number...]
# tools/og/render-og.sh # render 01..06
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usage comment says the no-arg invocation renders 01..06, but the actual default also includes 01-dyslexic. Update the usage examples to reflect the real default output set (7 renders) to avoid confusion.

Suggested change
# tools/og/render-og.sh # render 01..06
# tools/og/render-og.sh # render 01..06 and 01-dyslexic

Copilot uses AI. Check for mistakes.
Comment thread tools/og/render-og.sh
Comment on lines +15 to +21
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
SRC="file://${REPO}/docs/og.html"
OUT="${REPO}/docs/img/og"

if [[ ! -x "$CHROME" ]]; then
echo "Could not find Chrome at: $CHROME" >&2
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CHROME is hard-coded to the macOS app bundle path, so the script fails on Linux/CI or on Macs where Chrome isn’t installed in /Applications (or where Chromium is used). Consider allowing CHROME to be overridden via an environment variable and/or falling back to command -v google-chrome / chromium / chrome for better portability.

Suggested change
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
SRC="file://${REPO}/docs/og.html"
OUT="${REPO}/docs/img/og"
if [[ ! -x "$CHROME" ]]; then
echo "Could not find Chrome at: $CHROME" >&2
find_chrome() {
local candidate
candidate="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
if [[ -x "$candidate" ]]; then
echo "$candidate"
return 0
fi
for candidate in google-chrome chromium chromium-browser chrome; do
if candidate="$(command -v "$candidate" 2>/dev/null)"; then
echo "$candidate"
return 0
fi
done
return 1
}
CHROME="${CHROME:-$(find_chrome || true)}"
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
SRC="file://${REPO}/docs/og.html"
OUT="${REPO}/docs/img/og"
if [[ -z "$CHROME" || ! -x "$CHROME" ]]; then
echo "Could not find Chrome/Chromium. Set CHROME to a browser executable path or install google-chrome/chromium/chrome." >&2

Copilot uses AI. Check for mistakes.
Comment thread tools/og/render-og.sh
Comment on lines +77 to +96
if [[ -x "$PY_BIN" ]]; then
"$PY_BIN" - "$CROP_H" "$WIN_W" "${patterns[@]/#/${OUT}/og-}" <<'PY' || true
import sys
try:
from PIL import Image
except ModuleNotFoundError:
print("Pillow not available — skipping crop. Install with: /tmp/og-venv/bin/pip install Pillow", file=sys.stderr)
sys.exit(0)
crop_h = int(sys.argv[1]); crop_w = int(sys.argv[2])
for path in sys.argv[3:]:
if not path.endswith('.png'):
path = path + '.png'
try:
img = Image.open(path)
except FileNotFoundError:
continue
cropped = img.crop((0, 0, crop_w, crop_h))
cropped.save(path)
PY
fi
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The crop step suppresses all errors (... <<'PY' || true) and also exits 0 when Pillow is missing, which can silently leave behind 1920×1170 screenshots while still printing a “Rendered …” summary. If the cropped 1920×1080 output is required for the committed OG assets, prefer failing the script when crop can’t run (or at least emitting a clear non-success exit code unless an explicit "skip crop" flag is set).

Suggested change
if [[ -x "$PY_BIN" ]]; then
"$PY_BIN" - "$CROP_H" "$WIN_W" "${patterns[@]/#/${OUT}/og-}" <<'PY' || true
import sys
try:
from PIL import Image
except ModuleNotFoundError:
print("Pillow not available — skipping crop. Install with: /tmp/og-venv/bin/pip install Pillow", file=sys.stderr)
sys.exit(0)
crop_h = int(sys.argv[1]); crop_w = int(sys.argv[2])
for path in sys.argv[3:]:
if not path.endswith('.png'):
path = path + '.png'
try:
img = Image.open(path)
except FileNotFoundError:
continue
cropped = img.crop((0, 0, crop_w, crop_h))
cropped.save(path)
PY
fi
if [[ ! -x "$PY_BIN" ]]; then
echo "Python 3 is required to crop rendered screenshots to ${WIN_W}×${CROP_H}." >&2
exit 1
fi
"$PY_BIN" - "$CROP_H" "$WIN_W" "${patterns[@]/#/${OUT}/og-}" <<'PY'
import sys
try:
from PIL import Image
except ModuleNotFoundError:
print("Pillow is required to crop rendered screenshots. Install with: /tmp/og-venv/bin/pip install Pillow", file=sys.stderr)
sys.exit(1)
crop_h = int(sys.argv[1]); crop_w = int(sys.argv[2])
for path in sys.argv[3:]:
if not path.endswith('.png'):
path = path + '.png'
try:
with Image.open(path) as img:
cropped = img.crop((0, 0, crop_w, crop_h))
cropped.save(path)
except FileNotFoundError:
print(f"Rendered screenshot not found: {path}", file=sys.stderr)
sys.exit(1)
PY

Copilot uses AI. Check for mistakes.
Comment thread docs/index.html Outdated
Comment thread docs/index.html Outdated
Comment thread README.md Outdated
youtalk added 3 commits April 27, 2026 12:56
Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
@youtalk youtalk enabled auto-merge (squash) April 27, 2026 19:56
@youtalk youtalk merged commit e9c03b2 into main Apr 27, 2026
5 checks passed
@youtalk youtalk deleted the docs/og-cover-art branch April 27, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants