Defining Composer Templates
Templates in a Composer project are defined in the graphics.json file that needs to be placed in the root of the project folder.. Each entry in templates becomes a Studio layer, and the layer's fields array defines the editable payload fields shown in Studio.
Complete graphics.json example
This example includes one editable field for each Composer field type supported by the Studio payload editor.
{
"thumbnail": "thumbnails/project.png",
"templates": [
{
"id": "main",
"title": "Main Example Layer",
"thumbnail": "thumbnails/main.png",
"layer": "1",
"color": "#3498db",
"channel": "TEST CHANNEL",
"meta": {
"group": "Examples"
},
"fields": [
{
"id": "boolean_example",
"title": "Boolean",
"type": "BOOLEAN",
"value": true,
"meta": {},
"fields": []
},
{
"id": "integer_example",
"title": "Integer",
"type": "INTEGER",
"value": 7,
"meta": {
"minimum": 0,
"maximum": 99,
"step": 1
},
"fields": []
},
{
"id": "double_example",
"title": "Double (Float)",
"type": "DOUBLE",
"value": 0.75,
"meta": {
"minimum": 0,
"maximum": 1,
"step": 0.05,
"precision": 2
},
"fields": []
},
{
"id": "string_example",
"title": "String",
"type": "STRING",
"value": "Breaking News",
"meta": {},
"fields": []
},
{
"id": "text_example",
"title": "Text",
"type": "TEXT",
"value": "Line one\nLine two",
"meta": {
"singleLine": false,
"maxLines": 3,
"maxCharacters": 120,
"upperCase": false
},
"fields": []
},
{
"id": "text_single_example",
"title": "Single Line Text",
"type": "TEXT",
"value": "Single line value",
"meta": {
"singleLine": true,
"maxCharacters": 40,
"upperCase": true
},
"fields": []
},
{
"id": "color_example",
"title": "Color",
"type": "COLOR",
"value": "#ffcc00",
"meta": {},
"fields": []
},
{
"id": "image_example",
"title": "Image",
"type": "IMAGE",
"value": "media/logo.png",
"meta": {
"accept": ".png,.jpg,.jpeg,.webp"
},
"fields": []
},
{
"id": "video_example",
"title": "Video",
"type": "VIDEO",
"value": "media/clip.mp4",
"meta": {
"accept": ".mp4,.mov,.webm"
},
"fields": []
},
{
"id": "audio_example",
"title": "Audio",
"type": "AUDIO",
"value": "media/music.mp3",
"meta": {
"accept": ".mp3,.wav,.aac"
},
"fields": []
},
{
"id": "media_example",
"title": "Media",
"type": "MEDIA",
"value": "media/background.mp4",
"meta": {
"accept": ".png,.jpg,.mp4,.mov,.mp3,.wav"
},
"fields": []
},
{
"id": "clock_example",
"title": "Clock",
"type": "CLOCK",
"value": {
"mode": "COUNTDOWN",
"start": 60,
"stop": 0,
"direction": "DOWN",
"stoppable": true
},
"meta": {
"stoppable": true,
"direction": true,
"format": "mm:ss"
},
"fields": []
},
{
"id": "vertex2d_example",
"title": "Vertex2D",
"type": "VERTEX2D",
"value": {
"x": 100,
"y": 200
},
"meta": {
"minimum": -1000,
"maximum": 1000,
"step": 1,
"precision": 0,
"linked": false
},
"fields": []
},
{
"id": "vertex3d_example",
"title": "Vertex3D",
"type": "VERTEX3D",
"value": {
"x": 100,
"y": 200,
"z": 300
},
"meta": {
"minimum": -1000,
"maximum": 1000,
"step": 0.1,
"precision": 1,
"linked": false
},
"fields": []
},
{
"id": "action_example",
"title": "Action",
"type": "ACTION",
"value": false,
"meta": {},
"fields": []
},
{
"id": "options_example",
"title": "Options (Dropdown)",
"type": "OPTIONS",
"value": "lowerThird",
"meta": {
"mode": "DROPDOWN",
"options": [
{
"id": "lowerThird",
"title": "Lower Third"
},
{
"id": "fullFrame",
"title": "Full Frame"
},
{
"id": "ticker",
"title": "Ticker"
}
]
},
"fields": []
},
{
"id": "options_radio_example",
"title": "Options (Radio)",
"type": "OPTIONS",
"value": "left",
"meta": {
"mode": "RADIO",
"options": [
{
"id": "left",
"title": "Left"
},
{
"id": "center",
"title": "Center"
},
{
"id": "right",
"title": "Right"
}
]
},
"fields": []
},
{
"id": "table_example",
"title": "Table",
"type": "TABLE",
"value": [
{
"index": 0,
"fields": [
{
"id": "name",
"value": "Alice"
},
{
"id": "points",
"value": 10
},
{
"id": "active",
"value": true
}
]
},
{
"index": 1,
"fields": [
{
"id": "name",
"value": "Bob"
},
{
"id": "points",
"value": 8
},
{
"id": "active",
"value": false
}
]
}
],
"meta": {
"minimum": 1,
"maximum": 5,
"columns": [
{
"id": "name",
"title": "Name",
"type": "STRING",
"value": "",
"meta": {},
"fields": []
},
{
"id": "points",
"title": "Points",
"type": "INTEGER",
"value": 0,
"meta": {
"minimum": 0,
"maximum": 99,
"step": 1
},
"fields": []
},
{
"id": "active",
"title": "Active",
"type": "BOOLEAN",
"value": true,
"meta": {},
"fields": []
}
]
},
"fields": []
}
]
}
]
}
Field object shape
Every field should use this base shape:
{
"id": "fieldId",
"title": "Field Label",
"type": "STRING",
"value": "Default value",
"meta": {},
"fields": []
}
Common properties:
id: The key sent to the Composer graphic.title: The label displayed in Studio.type: One of the supported type strings.value: The default value.meta: Type-specific editor options.fields: Nested child fields. Use this forNONEcontainers and nested groups.
Supported editable types
| Type | Value shape | Useful meta options |
|---|---|---|
NONE |
Usually null |
hidden: true to hide a container from the editor |
BOOLEAN |
true or false |
None |
INTEGER |
Number | minimum, maximum, step |
DOUBLE |
Number | minimum, maximum, step, precision |
STRING |
String | None |
TEXT |
String | singleLine, maxLines, maxCharacters, upperCase |
COLOR |
Color string, for example #ffcc00 |
None |
IMAGE |
Media path string | accept |
VIDEO |
Media path string | accept |
AUDIO |
Media path string | accept |
MEDIA |
Media path string | accept |
CLOCK |
Clock object | stoppable, direction, format |
VERTEX2D |
{ "x": 0, "y": 0 } |
minimum, maximum, step, precision, linked |
VERTEX3D |
{ "x": 0, "y": 0, "z": 0 } |
minimum, maximum, step, precision, linked |
ACTION |
true or false |
None |
OPTIONS |
Selected option id | options, mode |
TABLE |
Array of rows | columns, minimum, maximum |
Options fields
OPTIONS fields need meta.options. meta.mode can be DROPDOWN or RADIO.
{
"id": "style",
"title": "Style",
"type": "OPTIONS",
"value": "lowerThird",
"meta": {
"mode": "DROPDOWN",
"options": [
{
"id": "lowerThird",
"title": "Lower Third"
},
{
"id": "fullFrame",
"title": "Full Frame"
}
]
},
"fields": []
}
Table fields
TABLE fields define columns in meta.columns. The editable row values are stored in value.
{
"id": "rows",
"title": "Rows",
"type": "TABLE",
"value": [
{
"index": 0,
"fields": [
{
"id": "name",
"value": "Alice"
},
{
"id": "score",
"value": 10
}
]
}
],
"meta": {
"minimum": 1,
"maximum": 10,
"columns": [
{
"id": "name",
"title": "Name",
"type": "STRING",
"value": "",
"meta": {},
"fields": []
},
{
"id": "score",
"title": "Score",
"type": "INTEGER",
"value": 0,
"meta": {
"minimum": 0,
"maximum": 99
},
"fields": []
}
]
},
"fields": []
}
Runtime payload sent to Composer
When a page is loaded or updated, Studio sends the layer ids and field values to Composer. For the example above, the runtime payload is shaped like this:
{
"main": {
"boolean_example": true,
"integer_example": 7,
"double_example": 0.75,
"string_example": "Breaking News",
"text_example": "Line one\nLine two",
"text_single_example": "Single line value",
"color_example": "rgb(255, 204, 0)",
"image_example": "media/logo.png",
"video_example": "media/clip.mp4",
"audio_example": "media/music.mp3",
"media_example": "media/background.mp4",
"clock_example": {
"action": "COUNTDOWN",
"start": 60,
"end": {
"enabled": true,
"value": 0
},
"direction": "DOWN"
},
"vertex2d_example": {
"x": 100,
"y": 200
},
"vertex3d_example": {
"x": 100,
"y": 200,
"z": 300
},
"action_example": false,
"options_example": "lowerThird",
"options_radio_example": "left",
"table_example": [
{
"name": "Alice",
"points": 10,
"active": true
},
{
"name": "Bob",
"points": 8,
"active": false
}
]
}
}