---
title: "Dynamic Content"
canonical_url: https://docs.zvid.io/docs/templates/dynamic-content/
source: docs/templates/dynamic-content.md
content_revision: 6338386a1dd87e4a
---

# Dynamic Content

Beyond simple substitution, the template engine can **generate scenes from
arrays** and **show or hide content with flags** — the building blocks of
data-driven videos (product feeds, listings, leaderboards, reports).

## `iterate` — one scene per array item

Set `iterate` on a scene to the name of an **array variable**. The scene is
rendered once per item, in order:

This is a complete **project payload** for `payload` in a render request.
It creates three text cards without requiring external media:

```json
{
  "variables": {
    "products": [
      {
        "title": "Aurora Sneakers",
        "price": "$129"
      },
      {
        "title": "Nimbus Backpack",
        "price": "$89"
      },
      { "title": "Vega Watch", "price": "$249" }
    ]
  },
  "scenes": [
    {
      "id": "product",
      "iterate": "products",
      "duration": 3,
      "transition": "slideleft",
      "visuals": [
        {
          "type": "TEXT",
          "text": "{{item.title}} — {{item.price}}",
          "position": "center-center"
        }
      ]
    }
  ]
}
```

Inside an iterated scene:

- **`{{item}}`** is the current array element (rename it with
  `"iterateAs": "product"` → `{{product.title}}`).
- **`{{index}}`** is the zero-based position.
- Generated scenes get ids `product-1`, `product-2`, … and the scene's
  `transition` automatically **chains clone → clone**, with the last clone
  keeping the original transition target.

Your plan limits both items per iterated scene (`maxIterateItems`) and the
total expanded scene count (`maxScenes`). Retrieve the account-aware schema
and [validate the resolved request](https://docs.zvid.io/docs/validate-and-estimate/) instead of
assuming a shared limit. Stored video templates require explicit positive
scene durations, including each repeated scene.

## `condition` — show or hide

`condition` prunes a scene (or an element) when falsy. It takes a **boolean
flag** — a literal, a boolean variable, or a `{{flag}}` placeholder that
resolves to one (by design there is no expression language):

```json
{
  "variables": { "showOutro": false, "hasDiscount": true },
  "scenes": [
    {
      "id": "main",
      "duration": 3,
      "visuals": [
        { "type": "TEXT", "text": "20% OFF", "condition": "{{hasDiscount}}" }
      ]
    },
    {
      "id": "outro",
      "duration": 2,
      "condition": "{{showOutro}}",
      "visuals": []
    }
  ]
}
```

`iterate` and `condition` combine: the condition is evaluated **per item**, so
`"condition": "{{item.featured}}"` renders only the featured products.

## Validation & debugging

- `iterate` referencing a non-array (or undefined) variable is a field-level
  validation error.
- Pruned scenes/elements are counted in the render's resolution stats.
- The [editor's Variables panel](https://docs.zvid.io/docs/editor/templates/) previews iteration
  (first item) and condition results live on the stage, and flags undeclared
  variables before you save.
- Template preview resolves variables and returns project JSON/statistics;
  it does not render media. Use [Template basics](https://docs.zvid.io/docs/templates/template-basics/#save-and-preview-a-template)
  for the preview request, then [Validate and estimate](https://docs.zvid.io/docs/validate-and-estimate/)
  for the credit estimate.

## Put it together: bulk personalized videos

`iterate` builds the _inside_ of one video from data; [bulk
rendering](https://docs.zvid.io/docs/automation/bulk-rendering/) renders _many videos_ from many
variable sets. A product-feed pipeline typically uses both: one template,
`iterate` for the per-video product list, bulk `items` for per-customer or
per-category variants.
