Templates & Rendering

Repeater Elements

Repeater elements let you render variable-length lists, grids, and tables by passing an array of data items to a single template layer. Instead of building 10 separate text/image layers for 10 rows, y

Use Cases#

  • Invoice Line Items — a variable number of product rows, each with a description, quantity, and price
  • Leaderboards — a top-10 or top-N list of users with names, avatars, and scores
  • Product Grids — a 3×4 or 4×4 grid of product cards generated from a catalog array
  • Event Speakers — 1 to N speaker profiles on an event banner
  • Order Confirmations — a dynamic list of order items in a transactional email image

Plan Availability#

Repeater elements are available on Business and Enterprise plans. Attempting to render a template that contains a repeater on a Starter or Pro plan returns a 403 FEATURE_NOT_AVAILABLE error.


Building a Repeater in the Editor#

1. Add the Repeater#

Click Repeater in the toolbar. A dashed bounding box appears on the canvas — this is the repeater container. Resize and position it to define the area where your list or grid will live.

2. Enter Row Template Edit Mode#

Double-click the repeater on the canvas to enter Row Template Edit Mode. While in this mode:

  • A blue banner at the top of the canvas confirms you are editing the row template.
  • The Layers panel shows only the children of this repeater (not your other top-level elements).
  • Any element you add via the toolbar becomes a child of the repeater's row template.
  • Elements you add are positioned relative to the repeater's top-left corner — not the full canvas.

3. Design the Row Template#

Add text, image, shape, or QR code elements inside the repeater just as you would on the main canvas. Each element inside becomes one "cell" of a single row (or grid card).

Give each child element a unique API Name in the Properties panel. This becomes the key name you use in your data array. For example:

  • A text element for the product name → API Name: item_name
  • A text element for the price → API Name: item_price
  • An image element for a thumbnail → API Name: item_image

Mark child elements as Dynamic so they accept overrides from your data. You can also set their visibility to Auto if you want them to disappear when no value is provided.

4. Exit Edit Mode#

Click Done Editing Row Template in the banner (or press Escape) to return to the main canvas and continue designing.


Configuration Options#

Select the repeater (single-click while not in edit mode) to see its properties panel:

OptionDescription
API NameThe key used to pass the data array in your API request
DirectionVertical (stack rows top-to-bottom), Horizontal (side by side), or Grid
Row GapVertical spacing between items in pixels
Column GapHorizontal spacing between items in pixels (Grid mode)
ColumnsNumber of columns (Grid mode only)
Max ItemsCap the number of items rendered. Excess items are silently dropped.
Row HeightHeight of each row. Auto calculates from children; or set a fixed pixel value
Row WidthWidth of each row. Auto uses the repeater's full width; or set a fixed pixel value
Fallback Empty VisibleShow the row template even when no data is passed (useful for thumbnail previews)

API Integration#

POST API#

Pass the repeater's apiName as a key in your layers object. Its value must be an array of objects, where each object maps child API names to their values.

{
  "template": "invoice-template",
  "layers": {
    "line_items": [
      { "item_name": "Widget A", "item_price": "$10.00", "item_image": "https://example.com/a.png" },
      { "item_name": "Widget B", "item_price": "$20.00", "item_image": "https://example.com/b.png" },
      { "item_name": "Widget C", "item_price": "$30.00", "item_image": "https://example.com/c.png" }
    ]
  }
}

The render engine produces one row per array entry, stacked according to the Direction and gap settings.

Supported child layer types per item#

Child typeKey → value
Text"api_name": "string value"
Image"api_name": "https://..."
Rect / Ellipse"api_name": "#hexcolor"
QR Code"api_name": "https://..."

GET API (Dynamic Image URLs)#

GET URLs cannot contain raw JSON in query parameters. Instead, serialize your array as JSON, then Base64-encode it, and prefix the value with base64:.

Step-by-step:

const data = [
  { item_name: "Widget A", item_price: "$10.00" },
  { item_name: "Widget B", item_price: "$20.00" },
];
const encoded = "base64:" + btoa(unescape(encodeURIComponent(JSON.stringify(data))));
// Use encoded as the value for your repeater parameter

The resulting URL looks like:

/api/v1/render?apiKey=rs_get_...&template=invoice-template&line_items=base64:W3siaXRlbV9uYW1lIjoiV2lkZ2V0IEEiLCJpdGVtX3ByaWNlIjoiJDEwLjAwIn0seyJpdGVtX25hbWUiOiJXaWRnZXQgQiIsIml0ZW1fcHJpY2UiOiIkMjAuMDAifV0=

Using the GET URL Builder#

The Generate GET URL dialog in the template editor handles encoding automatically:

  1. Open the template editor and click Generate GET URL (or use the toolbar button).
  2. Select a GET API key.
  3. For each repeater layer, a textarea input appears (instead of a single-line field). Paste or type a JSON array directly — no need to encode it manually.

Example of what to type in the textarea:

[
  { "item_name": "Widget A", "item_price": "$10.00" },
  { "item_name": "Widget B", "item_price": "$20.00" }
]

The builder parses your JSON, Base64-encodes it, and includes it in the generated URL automatically. If the JSON is invalid, that parameter is omitted from the URL.


How the Render Engine Processes Repeaters#

  1. The engine reads the repeater's data property — the passed-in array.
  2. For each item, it clones the row template elements.
  3. It applies the item's key→value pairs to each matching child (by API name).
  4. It positions each row according to the direction, gap, and row height/width settings.
  5. All cloned rows are composited into the final output image.

Child element coordinates are stored relative to the repeater's top-left corner. The engine adds the repeater's canvas position when placing each row.


Error Handling#

ConditionBehavior
data is not an arrayEmits a REPEATER_NOT_ARRAY warning in the X-Render-Warnings header; falls back to the row template if fallbackEmptyVisible is enabled
Empty array ([])No rows rendered; the repeater area is blank (or shows the template if fallbackEmptyVisible is on)
Max Items exceededExtra items are silently dropped; only the first N items render
Missing child keyThat child element renders with its default template value
Invalid base64 in GET URLREPEATER_DECODE_ERROR warning; repeater renders with its default template
Render on Starter/Pro planReturns 403 FEATURE_NOT_AVAILABLE