> ## Documentation Index
> Fetch the complete documentation index at: https://docs.craftkit.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Render pipelines

> The worker renders with one of three pipelines, chosen from the template's content. They differ in loop and dynamic-image support — pick the right one before authoring.

A render is not one engine. The worker inspects the published version's content and dispatches to
**one of three pipelines**. They are not interchangeable: loops and dynamic images only work on
some. Choose the pipeline when you author the template, because it determines what your `data` can
actually produce.

## How the pipeline is chosen

| Pipeline                | Selected when                                   | Engine                               |
| ----------------------- | ----------------------------------------------- | ------------------------------------ |
| **PDF overlay**         | the template's `templateType` is `pdf-overlay`  | pdfme fields on an uploaded base PDF |
| **Document mode**       | the content is a block layout (a `pages` array) | `@react-pdf/renderer`                |
| **Canvas (Handlebars)** | otherwise (canvas/section content)              | Handlebars → HTML → Puppeteer        |

`templateType` is surfaced on [`GET /v1/templates/:slug`](/api-reference/get-template). The split
between document mode and canvas is decided by the stored content shape, which depends on how the
template was authored.

## Capability matrix

| Capability                           | Document mode                    | Canvas (Handlebars)                 | PDF overlay                |
| ------------------------------------ | -------------------------------- | ----------------------------------- | -------------------------- |
| Scalar variables                     | ✅                                | ✅                                   | ✅                          |
| **Loops / arrays** (repeating table) | ❌ none                           | ✅                                   | ❌ fixed fields only        |
| **Dynamic images** from data         | ❌ static `src` only              | ✅ data-bound                        | ✅ data-bound (image field) |
| Signature **image**                  | ❌ (signature block is text-only) | ✅ via an `image` variable           | ✅ via an image field       |
| Variable-length tables               | ❌                                | ✅                                   | ❌                          |
| Best for                             | designed block documents         | data-heavy docs with repeating rows | filling a fixed PDF form   |

<Warning>
  **Document mode has no loop primitive and no data-bound images.** A loop declared in the manifest
  binds at the API but renders nothing in document mode, and an `image` variable has no data-bound
  block to render it. The builder's `repeatable` / `table` toggles are authoring hints only — they
  do not iterate at render time.
</Warning>

## Choosing a pipeline

<CardGroup cols={1}>
  <Card title="You need a repeating table (e.g. line items, inspection areas)" icon="table">
    Author on the **Canvas (Handlebars)** pipeline. It is the only pipeline that iterates a loop
    into repeated rows. See [Variables & loops](/guides/variables-and-loops).
  </Card>

  <Card title="You need a dynamic / signature image" icon="image">
    Use **Canvas** (bind an `image` variable) or **PDF overlay** (an image field). See
    [Images & signatures](/guides/images-and-signatures).
  </Card>

  <Card title="You are filling a fixed, pre-designed PDF form" icon="stamp">
    Use **PDF overlay** — upload the base PDF and stamp typed fields (text, image, QR) onto it.
  </Card>

  <Card title="It is a designed block document, no arrays" icon="file-lines">
    **Document mode** is the simplest and the default of the modern builder.
  </Card>
</CardGroup>

<Note>
  Migrating a template from canvas content to a document-mode block layout **removes** loop and
  dynamic-image support. If a template relies on either, keep it on the canvas pipeline.
</Note>
