> For the complete documentation index, see [llms.txt](https://docs.scaleflex.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.scaleflex.com/developers-headless/studio/template-builder/getting-started.md).

# Getting started

Install the package, put the element on the page, hand it a credential and a template. This page gets an editor on screen; the pages after it go into the choices it glosses over.

### Install

```bash
npm i @scaleflex/template-builder
```

Or from the CDN, which registers the element on load:

```html
<script type="module" src="https://cdn.cloudimage.io/template-builder/0.7.2/template-builder.min.js"></script>
```

Pin the major version. The CDN bundle carries its own copy of Lit.

### Package exports

| Entry                                | Contents                                                                              |
| ------------------------------------ | ------------------------------------------------------------------------------------- |
| `@scaleflex/template-builder`        | The element class and every protocol constant and type. Does **not** register the tag |
| `@scaleflex/template-builder/define` | Side-effect import that registers `<sfx-template-builder>`                            |
| `@scaleflex/template-builder/react`  | The `<TemplateBuilder>` React wrapper, which also registers the tag                   |

{% hint style="warning" %}
**The package is client-only.** The element extends `HTMLElement`, so importing any of those three entries from a server-rendered module throws. In an SSR framework, import it dynamically on the client - `dynamic(..., { ssr: false })` in Next.js, or an import inside `useEffect`.
{% endhint %}

`react` and `react-dom` 18 or later are optional peer dependencies. The package works without React installed.

### A first embed

This is [stateless](/developers-headless/studio/template-builder/storage-modes.md) mode with a [security template](/developers-headless/studio/template-builder/authentication.md): your application owns the template, and no user of yours needs a Scaleflex identity. It is the usual shape for an external integration.

```html
<script type="module">
  import '@scaleflex/template-builder/define'
</script>

<sfx-template-builder
  base-url="https://templates.example.com"
  token="PROJECT_TOKEN"
  sec-template="SEC_TEMPLATE_KEY"
  stateless
  style="display:block;height:800px"
></sfx-template-builder>

<script type="module">
  const builder = document.querySelector('sfx-template-builder')

  // 1 - hand it the template to edit.
  const { content, name, templateQuery } = await fetch(`/api/templates/${id}`)
    .then((r) => r.json())
  builder.load({ templateId: id, name, content, templateQuery })

  // 2 - take the edit back and store it.
  builder.addEventListener('save', async (e) => {
    const { templateId, content, name, templateQuery } = e.detail
    const ok = await saveToYourApi(templateId, { content, name, templateQuery })
    builder.confirmSave(ok)
  })

  builder.addEventListener('error', (e) => console.error(e.detail))
</script>
```

Three things in that snippet matter more than they look:

* **`content` is a property, never an attribute.** Templates routinely exceed what fits in markup, so the document is handed over directly rather than through the DOM or a URL. `load()` is how you pass it.
* **`templateQuery` is not optional in practice.** It is what reopens the template on the render it was left at. [The render URL](/developers-headless/studio/template-builder/render-url.md) explains what it is and why dropping it changes what your images look like.
* **`confirmSave(ok)` is how a failed write stays visible.** The editor clears its unsaved-changes state the moment it emits `save`. Pass `false` and it restores the warning instead of showing a failed save as saved.

### The same thing in React

```tsx
import { TemplateBuilder } from '@scaleflex/template-builder/react'

<TemplateBuilder
  stateless
  baseUrl="https://templates.example.com"
  token={projectToken}
  secTemplate={secTemplateKey}
  templateId={id}
  content={xml}
  templateName={name}
  templateQuery={query}
  style={{ height: 800 }}
  onSave={async (data) => (await saveToYourApi(data)).ok}
/>
```

The wrapper reports save failures for you: return `false` from `onSave`, or throw, and the editor restores its dirty flag.

The credential props are a discriminated union, so the two [authentication modes](/developers-headless/studio/template-builder/authentication.md) are enforced when you compile rather than when a user opens the editor. Mixing them, or passing `secTemplate` without `stateless`, is a type error.

### Sizing, inline and modal

`mode` is `inline` by default, and an inline editor fills the box you give it - so give it one. An element with no height renders nothing.

```html
<sfx-template-builder style="display:block;height:800px" ...></sfx-template-builder>
```

`mode="modal"` covers the viewport instead and **starts closed**, rendering nothing until you call `open()`. In React that means reaching the element through a ref:

```tsx
import { useRef } from 'react'
import { TemplateBuilder } from '@scaleflex/template-builder/react'
import type { SfxTemplateBuilder } from '@scaleflex/template-builder'

const builder = useRef<SfxTemplateBuilder>(null)

<TemplateBuilder ref={builder} mode="modal" baseUrl={...} {...auth} />
<button onClick={() => builder.current?.open()}>Edit template</button>
```

### If nothing appears

The most common cause is not a bug in your code: your origin is not in the deployment's allowlist, and the browser refuses to load the frame. You get an empty box and a `handshake-timeout`. See [Embedding and origins](/developers-headless/studio/template-builder/embedding-and-origins.md), and [Troubleshooting](/developers-headless/studio/template-builder/troubleshooting.md) for the rest of the symptoms.

### Where to go next

* [Storage modes](/developers-headless/studio/template-builder/storage-modes.md) - who owns the template document
* [Authentication](/developers-headless/studio/template-builder/authentication.md) - which credential, and how to scope it
* [API reference](/developers-headless/studio/template-builder/api-reference.md) - the full surface
