Templates & Rendering

Using Dynamic Layers

Layers are the core building blocks of RenderStack templates. Each element on the canvas is a layer, and layers can be either static or dynamic. Understanding how layers work is essential to getting t

Why Layers Matter#

Every template you create is made up of layers stacked on top of each other — text, images, shapes, and lines. When you render a template via the API, you can override specific layers with custom data, turning a single design into thousands of unique images automatically. This is the core power of RenderStack.

Common use cases:

  • Social media graphics — Swap headlines, profile photos, and colors per post
  • Certificates & badges — Personalize names, dates, and achievement details
  • Product cards — Update prices, descriptions, and product images at scale
  • Event invitations — Customize guest names, venues, and event details
  • Ad creatives — A/B test different copy, images, and CTAs automatically

Static vs Dynamic Layers#

Static Layers#

Static layers display the same content every time the template is rendered. They form the fixed structure of your design. Use them for:

  • Background shapes and colors
  • Fixed logos or branding elements
  • Decorative elements that don't change
  • Layout borders or dividers

Static layers cannot be modified through the API — they always appear exactly as designed in the editor.

Dynamic Layers#

Dynamic layers are the key to automated image generation. They can be overridden via the API at render time, letting you inject custom content into your designs programmatically.

Why make a layer dynamic?

  • Personalization — Inject unique names, messages, or data per render
  • Automation — Generate hundreds of images from a single template without manual editing
  • Consistency — Maintain brand consistency while varying content
  • Efficiency — Design once, render infinitely with different data

How to make a layer dynamic:

  1. Select the element on the canvas
  2. Check Dynamic in the Properties panel

Each element has two name fields:

  • Name — The display name shown in the Layers panel (e.g., "Category Label")
  • API Name — The machine-friendly key used in API calls (e.g., category_label)

The API Name is automatically generated from the Name as a snake_case identifier. For example, a layer named "Speaker Photo" automatically gets an API Name of speaker_photo. The API Name auto-updates when you rename the layer, unless you've manually overridden it. You can also edit the API Name directly in the Properties panel to set a custom key.

Example API call with dynamic layers:

{
  "template": "social-post-template",
  "layers": {
    "headline": {
      "text": "Welcome to Our Event!"
    },
    "speaker_name": {
      "text": "Jane Smith"
    },
    "speaker_photo": {
      "src": "https://example.com/jane-photo.jpg"
    },
    "event_date": {
      "text": "March 15, 2026"
    },
    "accent_color": {
      "fill": "#ff6b35"
    },
    "ticket_qr": {
      "value": "https://example.com/ticket/12345"
    }
  }
}

Each key in the layers object corresponds to the API Name of a dynamic layer in the editor. Only dynamic layers can be overridden — static layers are ignored in API calls.

Layer Properties#

Common Properties#

All layer types share these properties:

PropertyDescription
NameDisplay name shown in the Layers panel
API NameMachine-friendly key (snake_case) used in API calls for dynamic layers. Auto-generated from Name but can be manually overridden
X, YPosition from top-left corner (pixels or percent of artboard)
Width, HeightDimensions (pixels or percent of artboard)
RotationAngle in degrees
OpacityTransparency (0 = invisible, 100 = fully visible)

Transform Units#

You can switch between pixels (px) and percent (%) for position and size values using the toggle in the Transform section:

  • px mode — Absolute pixel values
  • % mode — Values relative to the artboard, with a configurable reference dimension per property

Reference Dimension Selector (W/H Toggle)#

When using percent mode, each property (X, Y, Width, Height) has a W/H toggle that controls which artboard dimension the percentage resolves against:

  • W (Width-based) — The percentage resolves against the artboard width. This is the default for all properties.
  • H (Height-based) — The percentage resolves against the artboard height.

You can choose the reference dimension independently for each property, giving you precise control over how elements scale and reposition when the artboard aspect ratio changes.

Why width-based is the default: Using the artboard width as the reference for all properties (including Y and Height) follows CSS-style uniform spacing conventions. This ensures that equal percentage values produce equal pixel distances in both directions, regardless of aspect ratio.

Practical example: Setting both X and Y to 10% with width-based reference means both values resolve against the artboard width, ensuring equal pixel distance from the left and top edges regardless of aspect ratio. If your artboard is 1200×630, both X and Y resolve to 120px — creating perfectly uniform margins. If you later render at 1200×800, both still resolve to 120px, maintaining that uniform spacing.

When to use height-based reference: Choose height-based (H) when you want a property to scale proportionally with the artboard height instead. For example, a bottom-aligned element whose vertical offset should stay proportional to the canvas height as the aspect ratio changes.

Visibility Modes#

Each layer has a visibility mode that controls when it appears during rendering:

  • Visible — Always shown (default). The element renders regardless of whether dynamic data is provided.
  • Hidden — Never shown unless explicitly overridden by the API with visible: true.
  • Auto (Hide When Empty) — The element is completely hidden when its content is empty or not provided. No placeholder, no border, no frame — the element is entirely removed from the rendered output. When data is provided, it renders normally.

How Auto determines "empty" by element type:

  • Image layers — Hidden when src is empty or not provided
  • Text layers — Hidden when text, richText, and textRuns are all empty or not provided
  • QR Code layers — Hidden when the QR value (text) is empty or not provided
  • Shape layers (rect, ellipse, line) — Hidden when the element's visible flag is set to false (since shapes don't have "content" to evaluate, Auto mode checks the visible flag instead)

Each element is evaluated independently — hiding one element does not affect any other elements in the template.

Tip: Use Auto visibility for optional elements. For example, if your template has person1_avatar and person2_avatar, set the person2 elements to Auto so they are completely hidden when you only have one person's data. This avoids empty placeholder frames in the rendered output.

How to use with the GET URL: When generating a GET URL from the template editor, simply leave the field blank for any Auto-visibility layer you want hidden. The parameter will be omitted from the URL, and the element will not appear in the rendered image.

Overridable Properties by Type#

Text layers:

  • text — The displayed text content (plain string, uniform styling)
  • richText — Markdown-like shorthand for inline formatting (e.g., **bold**, *italic*, {sup}text{/sup}, {sub}text{/sub}, {color:#hex}text{/color}). See Rich Text & Inline Styling
  • textRuns — Structured JSON array of run objects for full per-character control over bold, italic, underline, strikethrough, color, highlight, font, fontSize, superscript, and subscript. Priority: textRuns > richText > text
  • fill — Text color
  • fontSize — Font size in pixels
  • fontFamily — Font family name

Image layers:

  • src — Image URL to display
  • fillMode — How the image fills its container (cover, contain, stretch, original)

QR Code layers:

  • value — The data to encode (URL, text, vCard, etc.)
  • darkColor — Color of the QR modules (hex color)
  • lightColor — Background color (hex color or "transparent")
  • errorCorrectionLevel — Error correction: "L", "M" (default), "Q", or "H"
  • margin — Quiet zone in modules (0–10)
  • cornerRadius — Corner radius (px or % based on unit setting)
  • cornerRadiusUnit — Unit for corner radius: "px" (default) or "%"

Shape layers (rect, ellipse):

  • fill — Fill color
  • stroke — Border color
  • strokeWidth — Border thickness (stored value; px or % based on unit setting)
  • strokeWidthUnit — Unit for stroke width: "px" (default) or "%" (percent of smaller dimension)
  • strokeWidthMin — Minimum stroke width in px (only applies when unit is "%")
  • strokeWidthMax — Maximum stroke width in px (only applies when unit is "%")
  • strokeAlign — Stroke alignment: "center" (default), "inner", or "outer"
  • cornerRadius — Corner radius (rect only; px or % based on unit setting)
  • cornerRadiusUnit — Unit for corner radius: "px" (default) or "%" (percent of smaller dimension, 50% = pill)
  • cornerRadiusMin — Minimum corner radius in px (only applies when unit is "%")
  • cornerRadiusMax — Maximum corner radius in px (only applies when unit is "%")

Pinning#

Pinning lets you anchor a layer's edges to the canvas edges or to other layers. This is powerful for creating layouts that maintain consistent spacing.

Each edge (top, left, bottom, right) can be pinned independently with:

  • A target — Canvas edge or any other layer in the template
  • An offset — Distance from the target, in either pixels or percent (toggle per edge)
  • A From anchor — Determines which side of the target the offset is measured from. For top/bottom pins, choose "Top", "Center", or "Bottom"; for left/right pins, choose "Left", "Center", or "Right". By default, each pin measures from the matching side (e.g., a top pin measures from the target's top). Changing the anchor lets you position relative to the opposite side or midpoint — for example, a top pin with anchor set to "Bottom" measures the offset from the bottom of the target, while "Center" measures from the target's vertical midpoint. Center anchors are especially useful when you want an element to be vertically or horizontally centered relative to a sibling element — for instance, a button in a row that should align to the vertical middle of adjacent content rather than aligning to an edge
  • Min/Max pixel clamp — When using percent offsets, you can optionally set minimum and maximum pixel values. The percent-based offset is computed first, then clamped to the min/max range. For example, an offset of 10% with Min=10px and Max=50px ensures the resolved offset stays between 10px and 50px regardless of canvas/element size.

How pinning and position compose: The pin anchor sets a reference point, and the element's own X/Y position from the Transform section acts as an additional offset from that anchor. For example, if you pin the top edge to the canvas at 0% and set Y to 10px, the element will be positioned 10px below the top of the canvas.

When opposite edges are both pinned (e.g., left and right), the element stretches to fill the space between them, and the element's own position/size is overridden by the pin anchors.

Layer Ordering#

Layers are rendered from bottom to top. The first layer in the list is drawn first (behind everything else), and the last layer is drawn on top.

Use the Layers panel on the left side of the editor to see and manage the layer stack.

Best Practices#

  1. Use descriptive names — Rename layers to descriptive names like "Profile Photo", "Event Title", or "Company Logo" instead of keeping the defaults. The API Name will automatically be generated as profile_photo, event_title, or company_logo
  2. Set sensible defaults — Always provide default content for dynamic layers so the template looks good in the editor and serves as a preview
  3. Group related elements — Name related layers with a consistent prefix (e.g., speaker_name, speaker_title, speaker_photo)
  4. Use Auto visibility — Set optional elements to Auto visibility so they are completely hidden (no placeholders) when data is not provided
  5. Test with the API — After designing, test your template with the render API to ensure dynamic layers work as expected
  6. Keep it simple — Start with a few dynamic layers and add more as needed; not every element needs to be dynamic