Skip to content

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 for NONE containers 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
      }
    ]
  }
}