UI templating
The following schema is used to define the UI which appears on the custom configuration forms used for custom plugins.
Using this templating system, you can quickly and easily define which fields are rendered to users and how user-provided values are mapped into a configuration.
Where the schema is used
The same field schema is used in two places, and a few field types only make sense in one of them.
In both locations the value is an array of field definitions, even when you only define one field:
[
{
"type": "password",
"name": "apiKey",
"label": "API key"
}
]Two types are specific to data stream parameters, because they depend on a dashboard being present: objects (which selects from the graph) and expression (which reads dashboard variables and timeframe values). Setting tileEditorStep on a field only has an effect in a data stream’s ui array for the same reason.
Common properties
Every field type accepts the following properties.
Three types are defined independently of this list and accept only their own properties: markdown, objects and script. In particular, none of them accept disabled or columnWidth.
Do not use the title property. It is deprecated in favor of help and has no effect.
Validation
The validation object holds the rules applied to a field’s value before the form can be submitted. Each rule is written either as a plain value, or as { "value": ..., "message": "..." } to supply your own error message.
{
"type": "text",
"name": "tenantId",
"label": "Directory (tenant) ID",
"validation": {
"required": true,
"minLength": {
"value": 36,
"message": "Must be a 36-character GUID"
},
"maxLength": 36
}
}Note that min and max on a number field live here, not on the field itself.
Match specs
Three properties take a match spec: matches on an objects field, visible on a field group, and disabled on any field. A match spec describes a set of conditions to test a value against.
A match spec can be written in four ways.
Inside an object, each key is the property being tested and each value is a clause:
Where a property holds an array of values, the positive clauses (equals, contains, oneOf, regex, any) pass if any item in the array matches, and the negative clauses (notEquals, notContains, notOneOf, notRegex) pass only if every item matches.
Conditional visibility
visible is only available on a field group, so to show or hide fields conditionally you wrap them in a field group and put visible on the group. A field group with no displayAs renders nothing of its own, its children appear exactly as if they were not grouped, so it works as a zero-cost wrapper that exists only to carry the condition.
[
{
"type": "radio",
"name": "authMode",
"label": "Authentication",
"options": [
{
"value": "basic",
"label": "Basic"
},
{
"value": "token",
"label": "Token"
}
]
},
{
"type": "fieldGroup",
"visible": {
"authMode": "basic"
},
"fields": [
{
"type": "text",
"name": "username",
"label": "Username"
},
{
"type": "password",
"name": "password",
"label": "Password"
}
]
}
]To match more than one value, use a clause:
{
"type": "fieldGroup",
"visible": {
"authMode": {
"type": "oneOf",
"values": [
"basic",
"digest"
]
}
},
"fields": []
}disabled takes the same match spec, but is a common property, so it can go directly on any field with no wrapper:
{
"type": "text",
"name": "region",
"label": "Region",
"disabled": {
"useDefaults": "yes"
}
}Matching a boolean field
Match specs compare values as strings, so a toggle is matched against "true" rather than true:
[
{
"type": "toggle",
"name": "useProxy",
"label": "Use a proxy"
},
{
"type": "fieldGroup",
"visible": {
"useProxy": "true"
},
"fields": [
{
"type": "text",
"name": "proxyUrl",
"label": "Proxy URL"
}
]
}
]A checkbox does not expose a value to match against at all. Give it a string value and match that instead:
[
{
"type": "checkbox",
"name": "showAdvanced",
"label": "Advanced options",
"value": "show"
},
{
"type": "fieldGroup",
"visible": {
"showAdvanced": "show"
},
"fields": []
}
]UI type definitions
An autocomplete dropdown that allows users to search and select from a predefined list of values. Use fixed values when the available options are known in advance and unlikely to change.
[{
"type": "autocomplete",
"name": "region",
"label": "Region",
"data": {
"source": "fixed",
"values": [
{
"value": "us-east-1",
"label": "US East (N. Virginia)"
},
{
"value": "us-east-2",
"label": "US East (Ohio)"
}
]
},
"allowCustomValues": true
}]A checkbox input for enabling or disabling a boolean option. Use defaultValue to control whether the checkbox is selected by default.
{
"type": "checkbox",
"name": "enabled",
"label": "Enable feature",
"defaultValue": true
}A selectable chip group that allows users to choose from a set of predefined options. Choice chips provide a compact, visual alternative to radio buttons or dropdowns for short lists of values.
{
"type": "choiceChips",
"name": "tags",
"label": "Tags",
"options": [
{
"value": "a",
"label": "Option A"
},
{
"value": "b",
"label": "Option B"
}
]
}A syntax-highlighted Monaco code editor for structured or multi-line content such as JSON payloads, SQL queries, scripts, or request bodies. Use the language property to enable appropriate syntax highlighting and editor behavior.
{
"type": "code",
"name": "body",
"label": "Request Body",
"language": "json"
}An expression input for dynamic values or logic-based configuration. Expressions support Mustache variables, allowing values to be injected dynamically at runtime, such as dashboard variables, timeframe values, or parameter inputs.
{
"type": "expression",
"name": "filter",
"label": "Filter Expression"
}A JSON editor for entering structured configuration data as valid JSON. Use this input when users need to supply complex objects, arrays, or nested configuration values.
{
"type": "json",
"name": "config",
"label": "Configuration"
}A key-value editor for entering collections of paired values such as HTTP headers, query parameters, environment variables, or metadata. Users can add, edit, and remove entries dynamically.
{
"type": "key-value",
"name": "headers",
"label": "Headers"
}A read-only Markdown content block for displaying formatted guidance, instructions, warnings, or contextual information within the configuration UI. Supports standard Markdown formatting such as headings, bold text, lists, and links.
{
"type": "markdown",
"name": "info",
"content": "**Note:** Replace the placeholder values below."
}A numeric input for integer or decimal values such as ports, thresholds, limits, or timeouts. Use defaultValue to provide an initial value when the field is first displayed.
{
"type": "number",
"name": "port",
"label": "Port",
"defaultValue": 443
}An object picker that allows users to select one or more indexed objects from the SquaredUp graph. Use it in a data stream’s ui array to let the tile filter the stream down to the objects the user picks.
matches controls which objects are selectable, and is required. It takes a match spec tested against the properties of each indexed object. The property you will reach for most often is sourceType, the object type as the plugin imported it:
{
"type": "objects",
"name": "project",
"label": "Project (optional)",
"matches": {
"sourceType": {
"type": "oneOf",
"values": [
"Vercel Project"
]
}
}
}To offer every indexed object, use the "all" shorthand:
{
"type": "objects",
"name": "scope",
"label": "Scope",
"matches": "all"
}To select objects of more than one type, list them in a single oneOf clause:
{
"type": "objects",
"name": "orgUnit",
"label": "Customer or Site (optional)",
"objectLimit": 1,
"matches": {
"sourceType": {
"type": "oneOf",
"values": [
"Customer",
"Site"
]
}
}
}The remaining properties:
Selected objects are stored as an array under the field’s name, even when only one is selected, and each object’s rawId is itself a single-element array. Treat an empty or absent value as “no filter applied” so the same data stream can serve both the account-wide and the per-object case.
A secure text input for sensitive values such as API keys, passwords, or tokens. Values entered into a password field are masked in the UI.
{
"type": "password",
"name": "apiKey",
"label": "API Key"
}A radio button group that allows users to select a single option from a small set of predefined values. Radio buttons are best used when all available options should be visible at once.
{
"type": "radio",
"name": "environment",
"label": "Environment",
"options": [
{
"value": "prod",
"label": "Production"
},
{
"value": "dev",
"label": "Development"
}
]
}A toggle-style selector that allows users to switch between a small set of predefined options. Switch inputs are best suited to simple view or mode changes where only one option can be selected at a time.
{
"type": "switch",
"name": "view",
"label": "View",
"options": [
{
"value": "table",
"label": "Table"
},
{
"value": "chart",
"label": "Chart"
}
]
}A single-line text input for freeform values such as hostnames, IDs, search terms, or query parameters. Use placeholder to provide an example or suggested format for the expected value.
{
"type": "text",
"name": "hostname",
"label": "Hostname",
"placeholder": "api.example.com"
}A multi-line text input for longer freeform content such as queries, descriptions, scripts, or notes. Use rows to control the initial visible height of the text area.
{
"type": "textarea",
"name": "query",
"label": "Query",
"rows": 5
}A toggle control for enabling or disabling a boolean setting. Toggles are best used for simple on/off configuration options. Use defaultValue to control the initial state of the toggle.
{
"type": "toggle",
"name": "advancedMode",
"label": "Advanced Mode",
"defaultValue": false
}Value shapes
Most fields store a single value under their name. Three do not, which matters when you read the value back in a plugin handler or reference it in a configuration.
Examples
The following examples show different use cases for the form elements you can define.
A password field for plugin setup
[
{
"type": "password",
"name": "apiKey",
"label": "API key",
"help": "Create an API key in the [provider portal](https://example.com/api-keys)",
"validation": {
"required": true
},
"placeholder": "e.g. sk_live_xxxxxxxxxxxxxxxx"
}
]A text field for data stream config
[
{
"name": "domain",
"type": "text",
"label": "Domain",
"placeholder": "mydomain.com",
"validation": {
"required": true
}
}
]Mapping field values
The name property of a UI field defines the variable name used when mapping user input into your configuration.
Values entered into the field can then be referenced using Mustache template expressions such as {{apiKey}}.
For example, if your plugin configuration requires an API key, you could create a password field named apiKey. The value entered by the user is then available at runtime through the matching Mustache variable.
{
"baseUrl": "https://api.example.com/{{apiKey}}",
"endpointPath": "domain/{{domain}}"
}[
{
"type": "password",
"name": "apiKey",
"label": "API Key"
}
]