Skip to content

Repository files navigation

opengraph

A fast, fluent, pure-Go renderer and CLI for 1200×630 Open Graph images. It supports cover-cropped PNG/JPEG/WebP backgrounds, gradients, linear-time blur, Bayer dithering, overlays, grids, wrapped text, custom fonts, and circular avatars. No CGO or external image tools are required.

Interactive TUI

Launch the terminal editor:

go run ./cmd/opengraph-tui

The TUI opens on one simple Create screen: choose an image, write the text, adjust blur/dither/overlay, and save. Press Tab only when you need the optional Advanced settings such as gradients, grids, avatars, fonts, colors, and dimensions. It uses the same renderer as the CLI.

↑ / ↓ or j / k  select a field
Enter            edit a field or advance a choice
← / →            adjust a number or choice
Tab              show/hide advanced settings
Ctrl+V or P      load an image directly from the system clipboard
R                 refresh the preview
S                 save the configured PNG
O                 open a full-size preview
Q                 quit

Clipboard image paste works through native platform adapters:

  • macOS: built-in AppleScript, with pngpaste used when installed
  • Wayland: wl-paste
  • X11: xclip
  • Windows: PowerShell clipboard APIs

Dragging an image file into an active path field also works in terminals that paste dropped file paths.

Command line

Build or run the command:

go build -o opengraph ./cmd/opengraph
go build -o opengraph-tui ./cmd/opengraph-tui
./opengraph --help

Create an image like the reference card:

./opengraph \
  --image background.png \
  --blur 12 \
  --dither 4,32 \
  --overlay '#00000099' \
  --title 'this is some bigger text on the top' \
  --subtitle 'ziggy zig zig zig (zig (btw)) (btw)' \
  --bottom '/zigging' \
  --output card.png

Use a gradient instead of an image:

./opengraph \
  --gradient '#0f0f0f,#222222,left-to-right' \
  --grid '40,1,#ffffff22' \
  --title 'a simple gradient background' \
  -o gradient.png

Generate only the dithered texture shown in the second reference:

./opengraph --background-color '#11131a' --dither 1,24 -o texture.png

Pipe PNG data to another program with --output -:

./opengraph --title 'hello' --output - > card.png

Quote colors containing # in shell commands. The CLI always applies layers in a safe order: background, blur, dither, overlay, grid, then crisp text and avatar.

Main flags

Area Flags
Canvas --width, --height, --padding, --output / -o
Background --image, --background-color, or --gradient START,END,DIRECTION
Effects --blur RADIUS, --dither DOT_SIZE,STRENGTH, --overlay COLOR, --grid SPACING,WIDTH,COLOR
Text --title, --subtitle, --bottom and corresponding --*-color flags
Type sizes --title-size, --minimum-title-size, --subtitle-size, --bottom-size
Fonts --title-font, --body-font (supply both)
Avatar --avatar, --avatar-size, --avatar-border-width, --avatar-border-color

Gradient directions are left-to-right, right-to-left, top-to-bottom, and bottom-to-top; ltr, rtl, ttb, and btt are accepted aliases.

Go library

package main

import (
    "log"

    og "opengraph"
)

func main() {
    card := og.Default().
        BackgroundImage("background.png").
        Blur(12).
        Dither(4, 32).
        Overlay("#000000cc").
        Title("the day i fell in love with a cactus", "#ffffffff").
        Subtitle("completely true story", "#ffffffff").
        Bottom("#real_life", "#ffffffff").
        AvatarWithBorder("avatar.jpg", 72, 3, "#fff")

    if err := card.Save("out.png"); err != nil {
        log.Fatal(err)
    }
}

Library operations execute in call order. Fluent methods retain their first error, returned by Err, Write, or Save.

og.New(width, height)
og.Default() // 1200×630

card.BackgroundColor("#101010")
card.BackgroundImage("photo.webp")
card.LinearGradient("#0f0f0f", "#222222", og.LeftToRight)
card.Grid(40, 1, "#ffffff22")
card.Blur(12)
card.Dither(2, 32)
card.Overlay("#00000099")
card.Title("Wrapped title", "#fff")
card.Subtitle("Supporting copy", "#fff")
card.Bottom("example.com", "#fff")
card.Avatar("avatar.jpg", 72)
card.AvatarWithBorder("avatar.jpg", 72, 3, "#fff")
card.Padding(40)
card.FontSizes(60, 30, 24)
card.MinimumTitleSize(32)
card.LoadFonts("heading.ttf", "body.ttf")
card.Write(writer)
card.Save("card.png")

Colors accept #RGB, #RGBA, #RRGGBB, or #RRGGBBAA. Output is PNG.

Performance

Blur uses running horizontal and vertical channel sums, making it O(width × height) rather than scaling with blur radius. Gradients reuse rows/columns, dithering applies precomputed Bayer offsets, and parsed fonts are cached per card.

Run benchmarks with:

go test -bench=. -benchmem ./...

Credits

The original idea was inspired by The Kind Stranger at namishh.com. This project would not have popped into my head without them.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages