Introduction
Ogre is a pure Go alternative to Vercel’s Satori for converting HTML and CSS into SVG, PNG, and JPEG images. It is designed for generating OpenGraph images, social cards, and dynamic image content from templates.
What is this for?
Section titled “What is this for?”When you share a link on Twitter, Slack, Discord, or LinkedIn, a preview image appears. That image is an OpenGraph (OG) image. Instead of designing a static image for every page, you can generate them from an HTML template.
Ogre handles this. Write HTML with inline styles or Tailwind classes, pass it to Ogre, get an image back. Use it as a Go library, a standalone CLI, or a self-hosted HTTP server. Blog post cards, documentation pages, event banners, repo cards, or any dynamic image your application needs.
go install github.com/macawls/ogre/cmd/ogre@latestQuick look
Section titled “Quick look”result, _ := ogre.Render(` <div class="flex w-full h-full bg-slate-900 p-16 items-center justify-center"> <div class="text-5xl font-bold text-white">Hello World</div> </div>`, ogre.Options{Width: 1200, Height: 630})
os.WriteFile("og.svg", result.Data, 0644)Why this exists
Section titled “Why this exists”Dynamic image generation (OG cards, social previews, certificates, invoices) typically involves one of these:
- Satori requires a JavaScript runtime. For non-JavaScript backends, that means a separate service.
- Headless Chrome / Puppeteer uses hundreds of megabytes of RAM and takes seconds per render.
- Image manipulation libraries (like Go’s
imagepackage) work but require manual layout instead of HTML/CSS.
Ogre compiles to a single static binary with CGO_ENABLED=0. Add it as a dependency and call ogre.Render(), or run it as a standalone HTTP server.
| Ogre | Satori | |
|---|---|---|
| Binary | 11 MB static binary | JavaScript runtime required |
| Simple render | 0.03–0.08 ms | 0.3–2.5 ms |
| Complex render | 3–8 ms | 4–17 ms |
| Output | SVG, PNG, JPEG | SVG only |
| Use as library | go get, one function | npm package |
Render times measured on AMD Ryzen 5 5600H, 1200x630 renders, both producing SVG. Full benchmark data in Satori Comparison.
Design goals
Section titled “Design goals”- Pure Go. No CGo, no external binaries. Single static binary with
CGO_ENABLED=0. - Output quality first. The priority is correct, complete rendering — PNG/JPEG output, inline SVGs, box shadows, CSS filters, transforms, RTL text. Performance optimizations follow once output fidelity is solid.
- Tailwind built-in. Resolves Tailwind v3 utility classes directly. No build step needed.
- Production-ready server. Includes an HTTP server with LRU caching, rate limiting, and template support.
Dependencies
Section titled “Dependencies”Standard library, golang.org/x/*, and one external package:
golang.org/x/net/htmlfor HTML parsinggolang.org/x/image/fontfor font interfaces and rasterizationgolang.org/x/image/vectorfor 2D vector path rasterizationgolang.org/x/text/unicode/bidifor bidirectional textgithub.com/go-text/typesettingfor text shaping (kerning, ligatures, RTL)
Output formats
Section titled “Output formats”| Format | Content Type | Notes |
|---|---|---|
| SVG | image/svg+xml | Font glyphs embedded as path data. Self-contained. |
| PNG | image/png | Rasterized with gradient support. |
| JPEG | image/jpeg | Configurable quality (default 90). |