Skip to main content
The image node embeds a raster image, supplied as base64-encoded bytes inside the request.
{ "type": "image", "base64": "iVBORw0KGgoAAAANSUhEUgAA...", "fit": "fitWidth" }
FieldTypeRequiredNotes
base64stringyesThe raw image bytes, base64-encoded. No data: prefix.
fit"fitArea" · "fitWidth" · "fitHeight"noHow the image scales into its space. Default fitArea.
Tipar passes the decoded bytes to the renderer, which detects the format — common raster formats such as PNG and JPEG work. URL-sourced images are not supported in v1; the bytes must travel in the request.
Do not include the data:image/png;base64, prefix that browsers and some libraries prepend. Send only the base64 payload itself. A value the renderer can’t decode (bad base64, or an unsupported format) returns 422 template.invalid_content.

Producing the base64

Encode the file’s bytes — strip any data-URL prefix first.
import { readFile } from "node:fs/promises";

const base64 = (await readFile("logo.png")).toString("base64");
// → drop into template: { type: "image", base64, fit: "fitWidth" }

Controlling size with fit

fit decides how the image scales into the space its parent gives it. The space comes from the layout — most often a row cell with a constant width, or the page width inside a column.
fitBehaviour
fitArea (default)Scale to fit within both the available width and height, preserving aspect ratio.
fitWidthScale so the image is exactly as wide as its space; height follows the aspect ratio.
fitHeightScale so the image is exactly as tall as its space; width follows the aspect ratio.
A logo in a header lane is typically a fixed-width cell with fitWidth:
{
  "type": "row",
  "items": [
    { "size": { "kind": "constant", "width": 120 }, "child": { "type": "image", "base64": "{{logo}}", "fit": "fitWidth" } },
    { "size": { "kind": "relative", "weight": 1 }, "child": { "type": "text", "value": "{{company.name}}", "style": { "fontSize": 18, "bold": true }, "align": "right" } }
  ]
}
base64 is a text-like string, so it can be interpolated — "base64": "{{logo}}" pulls the encoded image from data. That keeps a large, static logo out of the template file and lets you swap it per tenant.
Images count toward the 4 MB request body cap. Optimise and resize before encoding — a 200 KB logo is plenty at print resolution, and base64 adds ~33% on top. Don’t ship a 5 MB photo where a downscaled one will do.

Next: Headers & footers

Repeat content on every page and add page numbers.