OG-image / social-card scenes rendered server-side, built to run on Fresco canvases.
An OG template is a design with holes — the post title, hero image,
and CTA label are substituted per post (and per locale) at render time,
not baked into the design. OpenFresco models that as a Scene of
positioned elements whose text/image values may be placeholders, then
resolves those values and emits the result.
This v0.1 slice produces SVG (render_svg/3) — the shared
intermediate representation. A later, optional native dependency will
rasterize the same SVG to PNG (render/3, not yet available). Because
both the editor preview and the final raster come from one SVG generator,
"what you edit is what renders" holds by construction.
Quick start
scene =
OpenFresco.Scene.new(width: 1200, height: 630, background: OpenFresco.Scene.solid("#0b1220"))
|> OpenFresco.Scene.add(
OpenFresco.Scene.text("title",
box: %{x: 64, y: 420, w: 1072, h: 150},
value: OpenFresco.Scene.placeholder("title"),
size: 68, weight: 700, fill: OpenFresco.Scene.solid("#ffffff")
)
)
svg = OpenFresco.render_svg(scene, %{"title" => "Hello, world"})Determinism & caching
render_svg/3 is a pure function of (scene, values). version/0
returns the generator version string — fold it into cache keys so cached
output invalidates when the generator changes.
Not fresco-coupled at render time
A Scene is standalone. It is carried inside a Fresco canvas's
extensions["open_fresco"] blob for editing and storage (non-breaking
for etcher/tessera, which own their own extension keys), but rendering
needs no fresco dependency — this package depends only on :jason.
Summary
Functions
Whether a PNG rasterizer backend is available (see render/3).
Render a scene to PNG bytes — {:ok, png, %{width, height}} or
{:error, term}. Browser-free, deterministic, never raises. Requires a
rasterizer backend (the optional :resvg dep, or a CLI on PATH); returns
{:error, :rasterizer_missing} when none is reachable. See
OpenFresco.Renderer.
Render a scene to SVG (a binary), resolving values.
The SVG-generator version string, for folding into cache keys.
Functions
@spec rasterizer_available?() :: boolean()
Whether a PNG rasterizer backend is available (see render/3).
@spec render(OpenFresco.Scene.t(), map(), keyword()) :: {:ok, binary(), %{width: pos_integer(), height: pos_integer()}} | {:error, term()}
Render a scene to PNG bytes — {:ok, png, %{width, height}} or
{:error, term}. Browser-free, deterministic, never raises. Requires a
rasterizer backend (the optional :resvg dep, or a CLI on PATH); returns
{:error, :rasterizer_missing} when none is reachable. See
OpenFresco.Renderer.
@spec render_svg(OpenFresco.Scene.t(), map(), keyword()) :: binary()
Render a scene to SVG (a binary), resolving values.
values maps {{slot}} (and [[global]]) names to resolved values.
Inline tokens are substituted inside text and image strings; an unwired
{{slot}} passes through visibly (og's "needs wiring" signal), and a
missing image slot draws the neutral "unresolved image" stand-in. Locale
is a render input — pass locale-resolved values (or a [[page_locale]]
global).
Options:
:globals— a map of[[global]]values (site host, page URL, locale…), merged withvaluesbefore substitution.:max_dimension— clamp canvas width/height to this many pixels (default10_000) as an OOM guard against crafted scenes.
@spec version() :: String.t()
The SVG-generator version string, for folding into cache keys.