Horizon Framework

UI API — Template

apiClient.ui.template manages Nunjucks templates — reusable content definitions used to render UI components like cards and list items.

Templates are fetched with persistence and SWR (stale-while-revalidate) caching, so they load instantly from the cache while a fresh copy is fetched in the background.

Template Kinds

Templates have a kind field (from UI.CRUD.Kind) that determines how they are rendered:

KindDescription
CARDCard template for summary views
LIST_ITEMRow template for list views
DETAILFull detail view template

Methods

create

Create a new template.

const template = await apiClient.ui.template.create({
  template: {
    name: 'Job Card',
    kind: 'CARD',
    content: '<div>{{ name }}</div>',
  },
})
console.log(template.uid)

get

Fetch a single template by UID.

const template = await apiClient.ui.template.get({ uid: 'abc123' })

getMany

Fetch multiple templates, with optional filters. Results are cached with SWR.

// All templates
const templates = await apiClient.ui.template.getMany({})

// By name
const named = await apiClient.ui.template.getMany({ name: 'Job Card' })

// Paginated
const page = await apiClient.ui.template.getMany({ limit: 20, page: 1 })

put

Update an existing template. Uses merge-and-put — only include the fields you want to change.

await apiClient.ui.template.put({
  template: {
    uid: 'abc123',
    content: '<div class="card">{{ name }}</div>',
  },
})

del

Delete a template by UID.

await apiClient.ui.template.del({ uid: 'abc123' })

getBestTemplate

Find the best-matching template by name (sorted by relevance). Returns null if none found.

const template = await apiClient.ui.template.getBestTemplate('Job Card')
if (template) {
  console.log(template.content)
}

Template Type

A template object contains the following key fields:

FieldTypeDescription
uidstringUnique identifier
namestringDisplay name
kindUI.CRUD.KindTemplate kind enum
contentstringNunjucks template string (defaults to '')

React Example

Security note: dangerouslySetInnerHTML renders Nunjucks template output directly into the DOM. Ensure all values in data come from trusted sources, or sanitize the rendered HTML with a library like DOMPurify before rendering. Template content itself should only come from trusted administrative sources, never from end-user input.

import { useApiClient } from '@skedulo/horizon-core'
import { useEffect, useState } from 'react'
import nunjucks from 'nunjucks'

const CardRenderer = ({ templateName, data }) => {
  const apiClient = useApiClient()
  const [html, setHtml] = useState('')

  useEffect(() => {
    apiClient?.ui.template.getBestTemplate(templateName).then((template) => {
      if (template) {
        setHtml(nunjucks.renderString(template.content, data))
      }
    })
  }, [apiClient, templateName, data])

  return <div dangerouslySetInnerHTML={{ __html: html }} />
}