The Template Builder scripting API provides a TypeScript-based interface for controlling and customizing the behavior of graphics templates within Viz Pilot Edge. Scripts are authored in the Monaco editor inside Template Builder, and execute at runtime in Viz Pilot Edge when users interact with templates.
Scripts have access to the template's payload fields, MOS metadata, life cycle events, view management, MSE playout control, etc, all through a set of globally available objects and functions documented below.
Global Objects
vizrt
The primary global object for interacting with the scripting API. Provides access to template fields, environment variables, Pilot metadata, MOS data, views, life cycle callbacks and spell check.
declare const vizrt: { readonly $env: Partial<Readonly<Record<string, string>>> readonly $pilot: PilotData readonly $data: Partial<Record<string, string>> readonly fields: Payload readonly views: readonly View[] onViewActivated: undefined | ViewActivatedCallback onCreate: undefined | (() => void) onLoad: undefined | (() => void) onClick: undefined | ((name: string) => void) onUpdate: undefined | ((fields: Payload, action: string) => void | Promise<void>) onAfterSave: undefined | (() => void) onBeforeSave: undefined | (() => boolean | Promise<boolean>) readonly spellCheck: (languageCode?: string, fields?: readonly string[]) => Promise<boolean> /** @deprecated Use `app.jumpToPreviewPoint` instead. */ readonly jumpToPreviewPoint: (name: string) => void}Property | Type | Description |
|---|---|---|
|
| Read-only access to environment variables defined for the template. |
|
| Read-only access to Pilot metadata including MOS data, Viz Mosart configuration, and element info. |
|
| Temporary key-value data store, accessible from dynamic drop-down editors. |
|
| The template's payload fields. The |
|
| Array of views (tabs) defined in the template model. Excludes the "All" tab which is a UI-only concept. |
app
Global object providing access to application-level commands such as UI notifications, MSE connections and preview navigation.
declare const app: { readonly notify: (severity: "warning" | "info" | "error" | "success", message: string) => void readonly createMseConnection: (url: string) => MseConnection readonly jumpToFieldPreview: (path: string) => void readonly jumpToPreviewPoint: (name: string) => void}Method | Description |
|---|---|
| Displays a notification toast in the UI with the given severity level and message text. |
| Creates a connection to a Media Sequencer Engine (MSE) at the specified REST URL. Returns an |
| Navigates the graphics preview to the field identified by the given path. |
| Navigates the graphics preview to a named preview point. |
Callbacks
Life cycle callbacks allow scripts to respond to events in the template life cycle. Assign a function to the corresponding property on the vizrt object to register a handler.
vizrt.onCreate
Called when a template is opened in Viz Pilot Edge, which creates a new Data Element. Typically used to initialize default values for fields.
Not triggered when creating a Data Element from an existing one (for example, duplicate).
Not triggered from Template Builder.
vizrt.onCreate = () => { vizrt.fields.$headline.value = "Default Headline"}vizrt.onLoad
Called when an existing data element is opened in Viz Pilot Edge. This event also fires in browse mode when a data element is selected. Use this event to prepare the MOS XML that is sent to the newsroom, which is relevant when data elements are sent directly from browse mode.
Not triggered from Template Builder.
vizrt.onLoad = () => { if (!vizrt.fields.$headline.value) { vizrt.fields.$headline.value = "Fallback" }}vizrt.onUpdate
This event is invoked by the Script Runner when the template is configured to use the Update Service. Note that this handler executes in a Node.js server process and, therefore, may expose a different JavaScript API. See Update Service for more details.
Not triggered from Template Builder or Viz Pilot Edge.
vizrt.onUpdate = async (fields: Payload, action: string) => { fields.headline.value = "Updated by automation"}vizrt.onBeforeSave
Called before a save operation. Return false (or a Promise<false>) to cancel the save, return true to proceed.
vizrt.onBeforeSave = () => { if (!vizrt.fields.$headline.value) { app.notify("error", "Headline is required") return false } return true}vizrt.onAfterSave
Called after a save operation of the currently open Data Element has completed successfully.
vizrt.onAfterSave = () => { app.notify("success", "Element saved")}vizrt.onClick
Called when a click event is triggered from an HTML fragment UI. The name parameter corresponds to the vizrt-click-name attribute of the clicked element.
vizrt.onClick = (name: string) => { if (name === "reset-button") { vizrt.fields.$headline.value = "" }}vizrt.onViewActivated
Called when the active view (tab) changes in the UI. Receives the index of the newly selected view and the previously selected view. An index of undefined means the "All" tab is selected.
vizrt.onViewActivated = (selected, old) => { if (selected !== undefined) { console.info(`Switched to view: ${vizrt.views[selected].title}`) }}Payload & Fields
Payload (Generated Interface)
The Payload type is generated at design time based on the template's VDF model. Each field defined in the model becomes a strongly-typed property on the Payload interface. The actual shape depends on the template.
Note: All field names in the generated Payload interface are prefixed with $ (for example, $headline, $body). This naming convention is applied automatically during type generation and distinguishes payload fields from built-in properties.
Access fields through vizrt.fields:
// Read a field valueconst title = vizrt.fields.$headline.value// Write a field valuevizrt.fields.$headline.value = "Breaking News"// Access a nested fieldvizrt.fields.$settings.$color.$value = "#FF0000"// Listen for external changes to a fieldvizrt.fields.$headline.onChanged = newValue => { console.info("Headline changed to:", newValue)}Field Types
EmptyField
The base interface for all VDF fields. Represents a field with no value and no list, only behavioral properties.
Info: If hidden, readOnly, or tip is undefined at the script level, the value is inherited from the field definition in the model, and further from the parent field.
interface EmptyField { /** Controls the visibility of the field. Inherited from parent and field definition. */ hidden: boolean /** Controls whether the field is read-only. Inherited from parent and field definition. */ readOnly: boolean /** The tooltip text for the field. Inherited from the field definition. */ tip: string /** An error message to display on the field. Not inherited. */ error: string /** The decoration object controlling display properties. */ decoration: BaseDecoration}ScalarField<T>
Extends EmptyField with a typed value (this is the most commonly used field type). T corresponds to the field's media type (for example, string, number, boolean, RichText, ImageAsset, etc.).
interface ScalarField<T> extends EmptyField { /** Read/write access to the field value. */ value: T /** Handler invoked when the value is changed from outside the script (e.g., by the user in the UI). */ onChanged?: (value: T) => void /** Read-only access to the field's metadata key-value pairs defined in the model. */ readonly metadata: Readonly<Map<string, string>> | undefined}TextScalarField<T>
Extends ScalarField<T> with text-specific decoration support. Used for single-line text, multi-line text and rich text fields.
interface TextScalarField<T = string> extends ScalarField<T> { /** Text-specific decoration with properties like maxlength. */ decoration: TextDecoration}VdfList<Columns>
Represents a list field containing rows of typed column values. The list is read-only (you cannot add or remove rows from script), but individual cell values can be modified.
type VdfList<Columns extends object> = ReadonlyArray<{ [Col in keyof Columns]: VdfListItem<Columns[Col]>}>Iterating a list example:
for (const row of vizrt.fields.$items) { console.info(row.label.value)}VdfListItem<T>
A mapped type that extracts the scriptable properties from a field type when used inside a list. For fields extending EmptyField, only properties starting with $ and the value property are preserved.
type VdfListItem<T> = T extends EmptyField ? { [K in Extract<keyof T, `$${string}` | "value">]: VdfListItem<T[K]> } : TDecoration Types
Decorations allow scripts to control the display properties of fields dynamically.
BaseDecoration
Base decoration available on all field types.
interface BaseDecoration { /** Display label for the field in the UI. */ label?: string}Example:
vizrt.fields.$headline.decoration.label = "Main Title"TextDecoration
Extended decoration for text fields, adding text-specific constraints.
interface TextDecoration extends BaseDecoration { /** Maximum number of characters allowed in the text field. */ maxlength?: number}Example:
vizrt.fields.headline.decoration.maxlength = 50Value Types
RichText
Represents formatted text content. RichText objects are immutable and must be created using the createRichText factory function.
interface RichText { /** The text content without any formatting (plain text representation). */ readonly plainText: string}MediaAsset
Base interface for all media asset values. Contains common metadata shared by image and video assets.
interface MediaAsset { /** The type of the media: `"image"` or `"video"`. */ readonly mediaType: MediaType /** The display title of the asset. */ readonly title: string | undefined /** Timestamp of the last update to the asset. */ readonly updated: Readonly<Date> | undefined /** URL to a thumbnail representation of the asset. */ readonly thumbnailUrl?: string | undefined /** The path to the media resource. */ readonly path: string}ImageAsset
Stores information about an image asset. Extends MediaAsset with dimensional metadata.
interface ImageAsset extends MediaAsset { /** The width of the image in pixels, if available. */ readonly width: number | undefined /** The height of the image in pixels, if available. */ readonly height: number | undefined}VideoAsset
Stores information about a video asset. Extends MediaAsset with dimensional and duration metadata.
interface VideoAsset extends MediaAsset { /** The width of video frames in pixels, if available. */ readonly width: number | undefined /** The height of video frames in pixels, if available. */ readonly height: number | undefined /** The duration of the video in seconds, if available. */ readonly duration: number | undefined}Duplet
Represents a two-dimensional value (media type "application/vnd.vizrt.duplet"). The object is immutable.
class Duplet { /** The x-value of the duplet. */ x: number /** The y-value of the duplet. */ y: number constructor(x: number, y: number)}Triplet
Represents a three-dimensional value (media type "application/vnd.vizrt.triplet"). The object is immutable.
class Triplet { /** The x-value of the triplet. */ x: number /** The y-value of the triplet. */ y: number /** The z-value of the triplet. */ z: number constructor(x: number, y: number, z: number)}VizMap
Represents a Viz Engine map value (media type "application/vnd.vizrt.curious.map"). Contains data in a |||-delimited envelope format (for example, Protocol=1|||XML=...|||). The object is immutable.
class VizMap { /** The raw `|||`-delimited map string. */ readonly mapString: string constructor(mapString: string)}MediaType
Union type for the supported media asset categories.
type MediaType = "image" | "video"View Management
Views represent tabs in the payload editor UI. They are defined in the template model and allow organizing fields into logical groups.
View
Represents a single view/tab. Scripts can read the active state, activate a view programmatically, change the display title and inspect contained items.
interface View { /** Whether this view is currently the active/selected tab. */ readonly isActive: boolean /** Activates this view, switching the UI to display this tab. */ readonly activate: () => void /** * A decorative title that can be set by scripts for display purposes. * Does not affect the underlying model. Resets to the model default on session reload. */ title: string /** The items contained in this view. */ readonly items: readonly ViewItem[]}Switching views example:
// Activate the second viewvizrt.views[1].activate()// Rename a view tabvizrt.views[0].title = "General Settings"ViewItem
A union type representing any item within a view. Either a field item or a UI item (fragment/iframe).
type ViewItem = FieldViewItem | UiViewItemFieldViewItem
A field item placed within a view, identified by its field path.
interface FieldViewItem extends BaseViewItem { readonly type: "field-item" /** The field path identifying this item within the payload. */ readonly path: string}UiViewItem
A UI item (HTML fragment or iframe) placed within a view, identified by its name.
interface UiViewItem extends BaseViewItem { readonly type: "ui-item" /** The name identifying this UI item. */ readonly name: string}BaseViewItem
Base interface for all view items, providing position management within the view's grid layout.
interface BaseViewItem { /** The current grid position and dimensions of this item. */ readonly position: Rect /** * Updates the position of this item. Accepts a partial `Rect` — provided * properties are merged with the existing position. */ readonly setPosition: (position: Partial<Rect>) => void /** The discriminator for the item type. */ readonly type: "field-item" | "ui-item" /** The field path (only set for field items). */ readonly path?: string /** The UI item name (only set for UI items). */ readonly name?: string /** Whether the view item is hidden or not in the view * * **Note**: Field's hidden expression evaluation overrides this value **/ hidden?: boolean}Rect
Defines a rectangle within the view's 2D grid layout system. All values are in grid units.
type Rect = { /** The x-coordinate (column) of this rectangle. */ readonly x: number /** The y-coordinate (row) of this rectangle. */ readonly y: number /** The width of this rectangle in grid columns. */ readonly width: number /** The height of this rectangle in grid rows. */ readonly height: number}Repositioning a field and a UI component in a view example:
const items = vizrt.views[0].itemsconst headlineItem = items.find(item => item.type === "field-item" && item.path === "headline")headlineItem?.setPosition({ x: 0, y: 0, width: 12, height: 2 })const myFragment = items.find(item => item.type === "ui-item" && item.name === "fragment")myFragment?.setPosition({ x: 6, y: 0, width: 5, height: 14 })Pilot Data
PilotData
Provides read-only access to Pilot-specific metadata associated with the current template, including MOS data, Viz Mosart configuration, and Data Element information.
type PilotData = { /** Read-only Mosart configuration defaults. */ readonly mosartConfig?: MosartConfig /** Mosart timing panel state, editable by scripts. */ readonly mosartTimingPanel?: MosartTimingPanel /** MOS item data — description, slug, abstract, timing, and MEM blocks. */ readonly mos: MOS /** Information about the current Data Element, if available. */ readonly element?: PilotElementInfo}PilotElementInfo
Contains identification information for the current Data Element.
type PilotElementInfo = { /** The unique identifier of the Data Element. */ readonly elementId?: string}MOS & MEM
MOS
Provides read/write access to MOS (Media Object Server) item fields (the standard metadata associated with newsroom items). Also provides access to MEM blocks and Viz Mosart timing values.
type MOS = { /** Mosart timing values (playout channel, timing, in/out modes). */ mosart?: MosartTimingValues /** Continue count for Mosart playout automation. */ continueCount?: number /** The MOS item description. */ description?: string /** The MOS item abstract. */ abstract?: string /** The MOS item slug. */ slug?: string /** Access to MOS External Metadata (MEM) blocks. */ readonly mem: MEMAccess}Setting MOS metadata example:
vizrt.$pilot.mos.description = "Election results lower third"vizrt.$pilot.mos.slug = "ELECTION-2026"MEMAccess
Provides CRUD operations for MOS External Metadata (MEM) blocks. MEM blocks are XML fragments stored within MOS items, each identified by a unique schema URL.
type MEMAccess = { /** Retrieves a MEM block by its schema URL, or `undefined` if not found. */ readonly get: (schema: string) => MEMBlock | undefined /** Creates or updates a MEM block. */ readonly set: (block: MEMBlock) => void /** Removes a MEM block by its schema URL. */ readonly delete: (schema: string) => void}Managing MEM blocks example:
// Set a custom MEM blockvizrt.$pilot.mos.mem.set({ schema: "http://example.com/schemas/custom-metadata", payload: "<metadata><key>value</key></metadata>", scope: "OBJECT",})// Read a MEM blockconst block = vizrt.$pilot.mos.mem.get("http://example.com/schemas/custom-metadata")if (block) { console.info("MEM payload:", block.payload)}// Remove a MEM blockvizrt.$pilot.mos.mem.delete("http://example.com/schemas/custom-metadata")MEMBlock
Represents a single MOS External Metadata block.
type MEMBlock = { /** The schema URL uniquely identifying this MEM block type. */ readonly schema: string /** The XML payload content of the MEM block. */ readonly payload: string /** The scope of the MEM block, determining its visibility and lifecycle. */ readonly scope: "PLAYLIST" | "STORY" | "OBJECT"}Scope | Description |
|---|---|
| The MEM block is scoped to the entire playlist. |
| The MEM block is scoped to the current story. |
| The MEM block is scoped to the individual MOS object. |
MosartTimingValues
Defines the Viz Mosart playout timing configuration for a template. These values control how the graphics element is triggered and removed during broadcast automation.
type MosartTimingValues = { /** The playout channel name. */ channel: string /** The start time for playout. */ start: string /** The duration of playout. */ duration: string /** The in-transition mode. */ inMode: InMode /** The out-transition mode. */ outMode: OutMode /** Whether this element is used as a locator graphic. */ isLocator: boolean}MosartConfig
Read-only Viz Mosart configuration defaults for the template. These values are set by the system and cannot be modified by scripts.
type MosartConfig = { /** Whether the Mosart timing panel should be displayed. */ readonly showTimingPanel: boolean /** The default playout destination channels. */ readonly destinations: readonly string[] /** Whether the "is Locator" checkbox should be shown by default in the timing panel. */ readonly showIsLocator: boolean}MosartTimingPanel
The editable state of the Viz Mosart timing panel for the current template. Scripts can control which options are available and the panel's default expanded state.
type MosartTimingPanel = { /** The playout destinations available for this template. */ destinations: readonly string[] /** Whether to display the "is Locator" checkbox. */ showIsLocator: boolean /** Whether to display the "Continue Count" option. */ showContinueCount: boolean /** Whether the timing panel is expanded by default. Defaults to `true`. */ expanded: boolean}InMode
The in-transition mode for Viz Mosart playout automation.
type InMode = "auto" | "manual"Value | Description |
|---|---|
| The graphic is taken on-air automatically by the automation system. |
| The graphic requires manual triggering by an operator. |
OutMode
The out-transition mode for Vi Mosart playout automation.
type OutMode = "auto" | "story-end" | "background-end" | "open-end"Value | Description |
|---|---|
| The graphic is taken off-air automatically after its duration. |
| The graphic remains on-air until the current story ends. |
| The graphic remains on-air until the background element ends. |
| The graphic remains on-air indefinitely until manually removed. |
MSE Connection & Playout
MseConnection
Provides methods for controlling graphics playout through a Media Sequencer Engine (MSE). Create an instance using app.createMseConnection(url).
type MseConnection = { sendVizCommand: (target: PlayoutTarget<undefined>, ...commands: readonly string[]) => void take: (target: PlayoutTarget<VizLayer>) => void update: (target: PlayoutTarget<VizLayer>) => void continue: (target: PlayoutTarget<VizLayer | string>) => void out: (target: PlayoutTarget<VizLayer | string>) => void checkConnection: () => Promise<boolean>}Method | Description |
|---|---|
| Sends one or more raw Viz Engine commands through the MSE. The |
| Executes a take command, bringing the graphic on-air on the specified target and layer. |
| Executes an update command, refreshing the on-air graphic with current field values. |
| Executes a continue command, advancing the graphic to its next animation state. |
| Executes an out command, removing the graphic from air on the specified target. |
| Returns a |
Playout workflow example:
const mse = app.createMseConnection("http://mse-host:8580")const target = { profile: "STUDIO_A", channel: "GFX", layer: "MAIN" as const }// Check connection firstconst connected = await mse.checkConnection()if (connected) { mse.take(target)}PlayoutTarget<Layer>
Identifies the MSE profile, channel and optional Viz Engine layer for a playout operation.
type PlayoutTarget<Layer> = { /** The MSE profile name. */ readonly profile: string /** The MSE channel name within the profile. */ readonly channel: string /** The Viz Engine layer to target. Defaults to `"MAIN"` if omitted. */ readonly layer?: Layer}VizLayer
The available Viz Engine rendering layers.
type VizLayer = "MAIN" | "FRONT" | "BACK"Layer | Description |
|---|---|
| The primary rendering layer for the main graphics scene. |
| The front layer, rendered on top of the main layer. |
| The back layer, rendered behind the main layer. |
Factory Functions
createRichText
Creates an immutable RichText object from a plain text string.
declare function createRichText(plainText: string, escape?: boolean): RichTextParameter | Type | Default | Description |
|---|---|---|---|
|
| — | The plain text content. |
|
|
| When |
Example:
vizrt.fields.$body.value = createRichText("Breaking news: <important>")// The "<important>" text is escaped and displayed literallyFormatted Text fields can be assigned by creating an object of type RichText in the method createRichText:
vizrt.fields.$name.onChanged = value => { vizrt.fields["$01-richtext"].value = createRichText( `<fo:wrapper bold="false" italic="false" underline="false">Hello </fo:wrapper>` + `<fo:wrapper bold="true" italic="true" underline="true">${value}!</fo:wrapper>`, false)}Info: The second argument to the method is set to false. This ensures the formatted text is sent to the Viz Engine unescaped. If set to true, the text is escaped, but the formatting is lost.
false: When the actual RichText XML should be sent to the Viz Engine.
true: When the text does not contain RichText, but contains characters that require escaping, such as < and >.
createImageAsset
Creates an ImageAsset object that can be assigned to Image fields.
declare function createImageAsset(image: string, title?: string): ImageAssetParameter | Type | Description |
|---|---|---|
|
| External URL, Graphic Hub image path or UUID. |
|
| Optional display title. Not required for Graphic Hub images. |
Example:
vizrt.fields.$insta.$image2.value = createImageAsset("IMAGE*<520E0100-56BD-5C4D-884D-5598ACFD75A4>")vizrt.fields.$insta.$image2.value = createImageAsset("IMAGE*01_GLOBALS/IMAGE/logo_wide")vizrt.fields.$insta.$image2.value = createImageAsset("https://images.pexels.com/photos/169647/pexels-photo-169647.jpeg", "HEY")createVideoAsset
Creates a VideoAsset from a local file path on the playout engine.
declare function createVideoAsset(video: string, title?: string): VideoAssetParameter | Type | Description |
|---|---|---|
|
| The file path to the video on the playout engine. Can be a full path or relative to the clip root on the Viz Engine. |
|
| Optional display title for the video. |
Example:
vizrt.fields.$00Video.value = createVideoAsset("C:\\clips\\CVJPHFMXDHBGZFMF.mxf", "Title")vizrt.fields.$00Video.value = createVideoAsset("opener.mxf", "Title")createImageAssetFromXml
Creates an ImageAsset from a raw XML string containing an atom:entry representation of the image.
declare function createImageAssetFromXml(imageXml: string): ImageAssetcreateVideoAssetFromXml
Creates a VideoAsset from a raw XML string containing an atom:entry representation of the video.
declare function createVideoAssetFromXml(videoXml: string): VideoAssetUtility Functions
reportErrors
Catches and reports errors from callback or asynchronous functions to the UI. Use this to wrap catch handlers in promise chains so that exceptions are surfaced to the user rather than silently swallowed.
declare function reportErrors(f: () => void, stage: string): voidParameter | Type | Description |
|---|---|---|
|
| A function to execute. Any exception thrown within it is reported to the UI. |
|
| A descriptive label for the operation, shown in the error notification. |
Example:
fetch("https://api.example.com/data") .then(response => response.json()) .then(data => { vizrt.fields.$headline.value = data.title }) .catch(e => reportErrors(() => { throw e }, "fetch data"), )Spell Check
vizrt.spellCheck
Invokes the spell check dialog on text fields. The user can review and correct misspelled words interactively.
readonly spellCheck: (languageCode?: string, fields?: readonly string[]) => Promise<boolean>Parameter | Type | Default | Description |
|---|---|---|---|
|
|
| The dictionary language code (e.g., |
|
| all text fields | An array of field paths to check. If omitted, all applicable text fields are checked. |
Returns Promise<boolean>, resolves to true if the spell check completed, or false if the user cancelled.
Example:
// Check all text fields in Norwegianconst completed = await vizrt.spellCheck("nb_NO")// Check specific fields onlyawait vizrt.spellCheck("en_US", ["headline", "body"])