Skip to content

vrypan/og-img

Repository files navigation

og

og is a small CLI for generating OpenGraph card images for blog posts and static sites. It renders a fixed HTML/CSS template to PNG or JPG, with content, colors, fonts, icons, and background images controlled by flags, frontmatter, and og.toml.

The default card size is 1200x630.

Quick Start

Install og and render a themed card:

brew tap vrypan/tap
brew install og-img
og render \
  --theme github-dark \
  --title "OpenGraph cards from the terminal" \
  --text "Theme presets, local assets, and reproducible rendering in a single CLI." \
  --site "github.com/vrypan/og-img" \
  --tags cli,rust,opengraph \
  -o og.png

To see all available themes, run:

og presets

Create a project config when you want repeated renders to share the same site, theme, output directory, or build settings:

og init

For example:

[content]
site = "notes.example.com"
default_theme = "catppuccin-mocha"

Then render with fewer flags:

og render \
  --title "A themed card" \
  --text "Project defaults keep repeated renders short." \
  --tags notes,static-site \
  -o og.png

Install

Using homebrew:

brew tap vrypan/tap
brew install og-img

To build from this repository:

cargo build --release

Run the binary directly:

./target/release/og --help

Or install it into Cargo's bin directory:

cargo install og-img

From a source checkout:

cargo install --path .

Common Examples

Use a background image:

og render \
  --title "Image-backed Cards" \
  --text "Background images are embedded into the generated card." \
  --bg-image test/bg.jpg \
  --bg-image-overlay "rgba(0,0,0,0.45)" \
  --fg "#ffffff" \
  --muted "#e2e8f0" \
  -o og.png

Write bytes to stdout:

og render --title "Hello" -o - > og.png

Commands

  • og render renders one card from flags, a markdown file, or stdin.
  • og build renders many markdown posts matched by a glob.
  • og init writes a starter og.toml.
  • og presets lists configured themes from shared defaults, user config, and project config.
  • og fonts lists known system font families.

Theme presets live in themes/ and are installed with release packages through defaults.toml.

Markdown Frontmatter

Use --from to render one markdown file:

og render --from posts/example.md -o static/og/example.png

Supported frontmatter:

---
title: Building OpenGraph Cards Without a Browser
date: 2026-07-09
tags: [rust, opengraph, templates]
description: Repeatable social preview images for static sites.
og:
  icon: assets/icon.png
  bg_image: assets/card-bg.jpg
  bg_image_overlay: rgba(0,0,0,0.45)
  theme: dark
---

description, summary, excerpt, or abstract becomes the card text. The markdown body is not used unless you explicitly pass --text -.

Configuration

og first loads optional shared defaults from defaults.toml, then optional user defaults, then discovers og.toml by walking up from the current directory, or you can pass --config path/to/og.toml.

Shared defaults are looked up with OG_DEFAULTS first, then <prefix>/share/og-img/defaults.toml. The repository defaults.toml contains the shared theme library.

User defaults are looked up with OG_CONFIG_HOME/og.toml first, then $XDG_CONFIG_HOME/og/config.toml, $XDG_CONFIG_HOME/og/og.toml, and finally ~/.config/og/config.toml on Unix-like systems.

Example:

[output]
dir = "static/og"
format = "png"
size = "og"
scale = 2.0
naming = "{slug}.png"
skip_unchanged = true

[content]
site = "notes.example.com"
icon = "assets/avatar.png"   # default icon for every card
date_format = "%-d %B %Y"
default_theme = "dark"
glob = "posts/**/*.md"

[fonts]
title = "Inter"
body = "Inter"
# title_file = "fonts/Inter-Bold.ttf"
# body_file = "fonts/Inter-Regular.ttf"

[themes.dark]
bg = "#101418"
fg = "#f2f4f8"
muted = "#8b95a5"
accent = "#5eead4"
tag_bg = "rgba(94,234,212,0.12)"
tag_fg = "#5eead4"
hairline = "rgba(255,255,255,0.08)"
bg_image_overlay = "rgba(0,0,0,0.35)"

Configuration is merged in this order:

built-in defaults <- defaults.toml <- user config <- og.toml <- selected theme <- frontmatter <- CLI flags

Useful Flags

Content:

--from <file.md>
--title <text>
--text <text>
--date <text>
--tags a,b,c
--site <name>
--icon <path>
--bg-image <path>
--monogram <char>

Theme and layout:

--bg <css-color>
--fg <css-color>
--muted <css-color>
--accent <css-color>
--tag-bg <css-color>
--tag-fg <css-color>
--bg-image-overlay <css-color>
--font-title <css-family>
--font-body <css-family>
--font-title-file <ttf>
--font-body-file <ttf>
--title-size <px>
--site-size <px>
--text-size <px>
--meta-size <px>
--radius <px>
--pad <px>
--theme <name>

Output:

--size og|twitter|square
--width <px>
--height <px>
--scale <number>
--format png|jpg
--check
-o, --output <path|->

Icons and background images must be local files; og never touches the network, so builds stay reproducible. To shrink PNGs further, run the standalone oxipng tool on the output.

Batch Builds

Render all posts:

og build --glob 'posts/**/*.md'

og build skips unchanged cards by default using a hash over the resolved card, output settings, template, and embedded assets. Use --force to rerender everything:

og build --force

Template

The card template lives in card.html and is embedded into the binary at compile time. Editing card.html requires rebuilding og.

The template is intentionally fixed: users customize content and design tokens, not the document structure.

Test Fixtures

Generate sample card variations:

./test/generate_variations.sh

The script writes example PNGs to test/.

License

MIT. See LICENSE.

About

A fast, single-binary CLI for generating OpenGraph card images for blog posts and static sites.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors