Variables are defined per template in template.json under the top-level variables array. There is no separate schema reference layer anymore, so the manifest is the source of truth.
Each entry in variables is a group. Each group contains items.
{
"variables": [
{
"name": "general",
"title": "General",
"description": "Base settings",
"items": [
{
"name": "service_name",
"type": "str",
"title": "Service name",
"default": "my-service"
},
{
"name": "environment",
"type": "enum",
"title": "Environment",
"value": "stage",
"config": {
"options": ["prod", "stage", "dev"]
}
}
]
}
]
}
Group fields:
nametitledescriptiontoggleneedsitemsItem fields:
nametypetitledescriptiondefaultvaluerequiredneedsextraconfigRuntime mapping notes:
title is used as the prompt labeldescription is used as the display/help textdescription is omitted, the runtime falls back to titlestrintfloatboolenumemailurlhostnamesecretType notes:
bool defaults to false when omitteddefault or value is providedsecret values are masked in prompts and display outputdefault vs valueUse default for the normal manifest default.
Use value when the template should pin the runtime value directly. If both are present, value wins.
Example:
{
"name": "environment",
"type": "enum",
"title": "Environment",
"default": "prod",
"value": "stage",
"config": {
"options": ["prod", "stage", "dev"]
}
}
Additional behavior is configured through config.
Supported fields:
placeholdertextareaunitoptionssliderminmaxstepautogenerated{
"name": "environment",
"type": "enum",
"title": "Environment",
"config": {
"options": ["prod", "stage", "dev"]
}
}
{
"name": "notes",
"type": "str",
"title": "Notes",
"config": {
"textarea": true,
"placeholder": "Optional notes"
}
}
{
"name": "replicas",
"type": "int",
"title": "Replicas",
"default": 3,
"config": {
"slider": true,
"min": 1,
"max": 9,
"step": 2,
"unit": "nodes"
}
}
config.autogenerated is supported only for secret variables.
Character-based example:
{
"name": "database_password",
"type": "secret",
"title": "Database password",
"config": {
"autogenerated": {
"kind": "characters",
"length": 40,
"characters": ["A", "B", "1", "2"]
}
}
}
Base64 example:
{
"name": "api_token",
"type": "secret",
"title": "API token",
"config": {
"autogenerated": {
"kind": "base64",
"bytes": 12
}
}
}
Rules:
defaultbytes, not lengthautogenerated on non-secret variables is rejectedneedsBoth groups and items support needs.
Examples:
"needs": "traefik_enabled=true""needs": "network_mode=bridge,macvlan""needs": "network_mode!=host""needs": "traefik_enabled=true;network_mode=bridge"Semantics:
= means the value must match!= means the value must not matchBehavior notes:
needs controls whether the group is considered availableneeds controls whether the item is shown and validatedfalse unless they were explicitly set via CLIGroups may define toggle, but the referenced toggle variable must exist as a boolean item in that same group.
{
"name": "traefik",
"title": "Traefik",
"toggle": "traefik_enabled",
"items": [
{
"name": "traefik_enabled",
"type": "bool",
"title": "Enable Traefik",
"default": false
},
{
"name": "traefik_host",
"type": "hostname",
"title": "Hostname"
}
]
}
If the toggle variable is missing, the runtime ignores the toggle.
For a loaded template, values are applied in this order:
default / value from template.json--var-file--varUse show against the template you care about:
boilerplates compose show nginx
boilerplates terraform show cloudflare-dns-record
That view reflects the actual runtime state for that template, including defaults, dependencies, toggle state, and file structure.