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:
| Option | Description |
|---|---|
| API Name | The key used to pass the data array in your API request |
| Direction | Vertical (stack rows top-to-bottom), Horizontal (side by side), or Grid |
| Row Gap | Vertical spacing between items in pixels |
| Column Gap | Horizontal spacing between items in pixels (Grid mode) |
| Columns | Number of columns (Grid mode only) |
| Max Items | Cap the number of items rendered. Excess items are silently dropped. |
| Row Height | Height of each row. Auto calculates from children; or set a fixed pixel value |
| Row Width | Width of each row. Auto uses the repeater's full width; or set a fixed pixel value |
| Fallback Empty Visible | Show 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 type | Key → 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:
- Open the template editor and click Generate GET URL (or use the toolbar button).
- Select a GET API key.
- 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#
- The engine reads the repeater's
dataproperty — the passed-in array. - For each item, it clones the row template elements.
- It applies the item's key→value pairs to each matching child (by API name).
- It positions each row according to the direction, gap, and row height/width settings.
- 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#
| Condition | Behavior |
|---|---|
data is not an array | Emits 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 exceeded | Extra items are silently dropped; only the first N items render |
| Missing child key | That child element renders with its default template value |
| Invalid base64 in GET URL | REPEATER_DECODE_ERROR warning; repeater renders with its default template |
| Render on Starter/Pro plan | Returns 403 FEATURE_NOT_AVAILABLE |
Related Documentation#
- Dynamic Layers — Marking elements as dynamic, API names, and visibility modes
- Dynamic Image URLs — Full reference for GET URL query parameters including repeater encoding
- URL Builder Tool — Building and testing GET URLs from the editor
- Render API Reference — POST API endpoints for sync, JSON, and batch rendering