A template's layers are stored as JSON in the Layout JSON field. The canvas size, background colour and background image are separate form fields, not part of the JSON.
Structure
{
"layers": [
{ "type": "rect", "x": 0, "y": 0, "width": 4, "height": 630, "color": "#6366f1" },
{ "type": "text", "content": "{{item.title}}", "x": 60, "y": 120,
"font_size": 52, "font_weight": "700", "color": "#ffffff",
"max_width": 680, "max_lines": 3, "line_height": 1.2 },
{ "type": "image", "src": "{{item.thumbnail_url}}", "fallback": "{{site.logo_url}}",
"x": 820, "y": 0, "width": 380, "height": 630, "fit": "cover" }
]
}
Layers are drawn in array order. A layer without a type, or with an unknown type, is skipped. An error while drawing one layer does not stop the others.
Geometry
x, y, width and height are integers in pixels by default. Two alternatives are accepted by the renderer but not exposed in the editor fields:
- Set
"unit": "percent"on a layer to interpret all four values as percentages of the canvas. - Give an individual value as a string ending in
%, for example"max_width": "60%".
Text layer
| Key | Default | Notes |
|---|---|---|
content |
Text with {{variables}}. Empty content draws nothing. |
|
x, y |
0 |
Top-left of the text block. |
font_size |
24 |
Points for GD's TrueType renderer. |
font_weight |
"400" |
bold, 700, 800 or 900 select the bold face. |
font_family |
"Inter" |
Family name; falls back to Inter when unknown. Not shown in the editor. |
color |
#ffffff |
Six-digit hex. Invalid values fall back to white. |
max_width |
canvas width minus x |
Wrap width in pixels. |
max_lines |
10 |
Extra lines are dropped; the last kept line is trimmed with an ellipsis. |
line_height |
1.3 |
Multiplier of font_size. |
Rectangle and line layers
| Key | Default | Notes |
|---|---|---|
x, y, width, height |
0 |
Filled rectangle. line is rendered identically to rect. |
color |
#ffffff |
Six-digit hex. |
Image layer
| Key | Default | Notes |
|---|---|---|
src |
Image URL, may contain variables. | |
fallback |
Used when src resolves to an empty string. |
|
x, y, width, height |
0 |
Layers with zero width or height are skipped. |
fit |
cover |
cover, contain or anything else for stretch (fill). |
overlay_color, overlay_opacity |
#000000, 0 |
Colour tint over the image; opacity 0 to 1. |
fade_edge, fade_color, fade_strength |
none, #000000, 0.8 |
Gradient from top, bottom, left or right. |
rotation |
0 |
Degrees; the result is cropped back to the layer box. |
shadow_blur, shadow_offset_x, shadow_offset_y, shadow_color |
0, 0, 0, rgba(0,0,0,0.5) |
Drop shadow. shadow_color accepts rgba(r,g,b,a), rgb(r,g,b) or hex. Blur needs Imagick. |
border_radius |
0 |
Editor preview only; ignored by the server renderer. |
How image URLs are loaded
Before fetching, the renderer tries to map the URL to a local file: for an absolute http(s) URL it takes the path component and looks for that file under the Omeka root; for a relative path it prepends the Omeka root. Files in Omeka's local files/ store are therefore read straight from disk. Anything else is fetched with file_get_contents, which requires allow_url_fopen and network access from the server. Unreadable or undecodable images are skipped silently.
Background
The template's Background color fills the canvas first. If Background image URL is set it is interpolated, loaded the same way as an image layer and drawn with cover fit across the whole canvas, before any layers.
Fonts
Inter Regular and Inter Bold are bundled in modules/OgImages/asset/font. Additional families can be registered by developers through the og_images_fonts global setting, a JSON-encoded array of objects with family, regular_file and bold_file keys, where the files are placed in the same font directory. There is no admin UI for this setting. A layer then selects the family with font_family.
Rendering without TrueType support
If GD was built without FreeType, text is drawn with GD's built-in bitmap font 5 at a fixed size, wrapped by character count. Font size, weight and family are ignored in that mode.