# Ogre — Full Documentation for LLMs > Pure Go HTML/CSS to SVG/PNG/JPEG renderer. Open-source Vercel Satori alternative. ## What is Ogre? Ogre converts HTML and CSS to images (SVG, PNG, JPEG) in pure Go. It is designed for generating OpenGraph images, social cards, and dynamic image content from templates. It is a drop-in alternative to Vercel's Satori that runs natively in Go with no JavaScript runtime required. No CGo, no external binaries — compiles to a single static binary with `CGO_ENABLED=0`. ## Installation ```bash # CLI go install github.com/macawls/ogre/cmd/ogre@latest # Library go get github.com/macawls/ogre ``` ## Go Library API ### One-shot render ```go result, err := ogre.Render(`
Hello World
`, ogre.Options{Width: 1200, Height: 630}) ``` ### Shared renderer (recommended for servers) ```go r := ogre.NewRenderer() result, err := r.Render(html, ogre.Options{Width: 1200, Height: 630, Format: ogre.FormatPNG}) ``` ### HTTP handler ```go r := ogre.NewRenderer() mux := http.NewServeMux() mux.Handle("POST /og", r.Handler(ogre.HandlerConfig{ Width: 1200, Height: 630, Format: ogre.FormatPNG, })) log.Fatal(http.ListenAndServe(":8080", mux)) ``` ### JSX-style builder ```go card := ogre.Div(ogre.Props{Class: "flex flex-col w-full h-full bg-slate-950 p-16"}, ogre.Div(ogre.Props{Class: "text-6xl font-extrabold text-white"}, "Hello World"), ogre.P(ogre.Props{Class: "text-2xl text-slate-400 mt-4"}, "Built with Ogre"), ) result, _ := card.Render(ogre.Options{Width: 1200, Height: 630}) ``` ### Types ```go type Options struct { Width int // Default: 1200 Height int // Default: 630 Format Format // "svg" (default), "png", or "jpeg" Quality int // JPEG quality 1-100 (default 90) Fonts []FontSource // Custom fonts Debug bool // Enable debug logging EmojiProvider string // "twemoji" (default) or "none" MaxElements int // Max HTML elements (0 = unlimited) } type FontSource struct { Name string // Font family name Weight int // 100-900 Style string // "normal" or "italic" Data []byte // Raw font bytes (TTF/OTF/WOFF) URL string // URL to fetch font (alternative to Data) } type Result struct { Data []byte // Rendered image bytes ContentType string // MIME type Width int Height int } type HandlerConfig struct { Width int // Default canvas width. Default: 1200. Height int // Default canvas height. Default: 630. Format Format // Default output format. Default: FormatPNG. Quality int // Default JPEG quality 1-100. Default: 90. } ``` ## CLI ```bash ogre --render template.html --output og.svg ogre --render template.html --output og.png --format png ogre --html '
Hi
' --output hi.png --format png ogre --serve --port 3000 ``` Flags: --render, --html, --output, --width (1200), --height (630), --format (svg/png/jpeg), --serve, --port (3000). ## HTTP Server ### Standalone server ```go srv := server.New(server.Config{ Addr: ":3000", CacheBytes: 64 << 20, RateLimit: 10, RenderTimeout: 10 * time.Second, MaxElements: 1000, CORSOrigin: "https://*.example.com,http://localhost:*", }) srv.Start() ``` ### Configuration from environment variables ```go cfg := server.ConfigFromEnv() srv := server.New(cfg) ``` | Variable | Default | Description | |----------|---------|-------------| | ADDR | :3000 | Listen address | | CORS_ORIGIN | * | Allowed CORS origin(s), comma-separated, supports wildcards | | CACHE_MB | 64 | LRU cache size in MB | | RATE_LIMIT | 0 | Requests per second per IP (0 = unlimited) | | TIMEOUT | 10 | Render timeout in seconds | | MAX_ELEMENTS | 1000 | Max HTML elements per render | ### CORS wildcard support CORS_ORIGIN supports comma-separated values with wildcard patterns: ```bash CORS_ORIGIN="https://*.example.com,http://localhost:*" ogre --serve ``` ## HTTP API Endpoints ### POST /render ```json { "html": "
Hello
", "width": 1200, "height": 630, "format": "png", "quality": 90, "fonts": [ { "name": "Inter", "weight": 400, "style": "normal", "url": "https://example.com/Inter-Regular.ttf" } ] } ``` Returns image bytes with appropriate Content-Type header. Response headers: - ETag: SHA-256 hash of input - X-Cache: HIT or MISS - Cache-Control: public, max-age=86400 (hits) or max-age=3600 (misses) ### POST /render/template ```json { "template": "
{{.Title}}
", "data": {"Title": "Hello"}, "format": "png" } ``` Uses Go html/template syntax. ### GET /health Returns `{"status":"ok"}`. ### GET /metrics Returns render statistics: ```json { "render_total": 150, "render_errors": 2, "cache_hits": 98, "cache_misses": 52, "total_duration_ms": 4200 } ``` ### Limits - Max request body: 10 MB - Max fonts per request: 5 - Max font size: 5 MB - Default cache: 64 MB - Default render timeout: 10 seconds - Default max elements: 1000 ## Supported CSS Properties Layout: display (flex, none, block), position (static, relative, absolute), width, height, min/max width/height, aspect-ratio, overflow, box-sizing. Flexbox: flex-direction, flex-wrap, flex-grow, flex-shrink, flex-basis, align-items, align-self, align-content, justify-content, gap. Box model: margin, padding, border (width, style, color), border-radius. Typography: font-family, font-size, font-weight, font-style, color, line-height, letter-spacing, text-align, text-transform, text-decoration, text-shadow, white-space, word-break, text-overflow, -webkit-line-clamp. Background: background-color, background-image (linear-gradient, radial-gradient, url()), background-size, background-position. Visual: opacity, box-shadow, transform, transform-origin, filter (blur, grayscale, brightness), object-fit. Note:
defaults to display: flex (matching Satori behavior, not browser behavior). ## Tailwind v3 Support Ogre resolves Tailwind CSS v3 utility classes at render time with no build step. Supported categories: layout, alignment, spacing, sizing, typography, colors (all palettes + shades), borders, shadows, opacity, position, filters (blur, brightness, grayscale), transforms (rotate, scale, translate, skew). Arbitrary values with bracket notation: `text-[32px] bg-[#ff5500]`. ## Font Support - Built-in Go fonts (zero config) - Google Fonts auto-resolution (CSS2 API, any font family) - Custom fonts from file data (TTF/OTF/WOFF) - Custom fonts from URL (auto-cached on disk) - WOFF2 not supported (convert to TTF/OTF first) ## Emoji Support Ogre supports emoji rendering with multiple providers: - Twemoji (default) — Twitter's emoji set - OpenMoji — open-source emoji - Noto — Google's Noto emoji SVG output embeds emoji as image references. PNG/JPEG output composites emoji bitmaps. ## RTL / Bidirectional Text Arabic, Hebrew, and other RTL scripts are supported via: - go-text/typesetting for HarfBuzz text shaping (ligatures, contextual forms) - golang.org/x/text/unicode/bidi for bidirectional reordering Complex scripts (Arabic, Hebrew, Devanagari, Thai) are automatically detected and shaped. ## Architecture Pipeline: HTML → Parse → Style → Layout → Render 1. Parse: HTML string to node tree (golang.org/x/net/html) 2. Style: Tailwind resolution, shorthand expansion, CSS inheritance 3. Layout: Custom W3C flexbox engine 4. Render: SVG (with font glyph paths embedded as path data) or PNG/JPEG rasterization ## Package Structure ``` ogre.go # Public API: Render(), NewRenderer() handler.go # HTTP handler: Renderer.Handler() jsx.go # JSX-style builder: Div(), Span(), etc. cmd/ogre/ # CLI entry point parse/ # HTML parsing → node tree style/ # CSS properties, Tailwind resolver, inheritance layout/ # Flexbox layout engine (W3C spec) font/ # Font loading, text measurement, glyph paths, shaping, emoji render/ # SVG generation, PNG/JPEG rasterization server/ # HTTP server, caching, templates, rate limiting ``` ## Dependencies - golang.org/x/net/html — HTML parsing - golang.org/x/image/font — font interfaces, OpenType parsing - golang.org/x/text/unicode/bidi — bidirectional text - github.com/go-text/typesetting — HarfBuzz text shaping for complex scripts (Arabic, Hebrew, etc.) No other third-party imports. No CGo. ## Docker ```bash docker build -t ogre . docker run -p 3000:3000 ghcr.io/macawls/ogre:latest ``` Multi-stage build, distroless base image. ## Public API A public instance is available at `https://ogre-api.macawls.dev` running the latest `ghcr.io/macawls/ogre` image. An interactive playground is available at `https://ogre.macawls.dev/getting-started/playground/`. ## Links - Docs: https://ogre.macawls.dev - Playground: https://ogre.macawls.dev/getting-started/playground/ - GitHub: https://github.com/macawls/ogre - Docker: https://github.com/macawls/ogre/pkgs/container/ogre