> The classic format for creating HTML graphics is... HTML Building an SPX template requires a specific HTML structure where the **Template Definition** (a JSON object in the `<head>`) acts as the brain, telling the system how to display controls and where to play the graphic. Templates consume data through the `spxData` object and follow a standard web development workflow using CSS for styling and JavaScript for animation logic. By organizing your files into a clean folder structure and utilizing various **Field Types**, you can create professional, data-driven graphics for any production. --- ## Basic Template Structure A typical SPX template follows this structure: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My Template</title> <!-- CSS Styles --> <style> /* Your styles here */ </style> <!-- JavaScript Libraries (optional) --> <script src="./js/library.js"></script> <!-- Template Definition (REQUIRED) --> <script> window.SPXGCTemplateDefinition = { // Template definition object }; </script> </head> <body> <!-- HTML Content --> <div id="content"> <!-- Your template content --> </div> <!-- Template Logic --> <script> // Your template JavaScript here // Access field values via spxData object </script> </body> </html> ``` ## Required Elements ### 1. Template Definition The `SPXGCTemplateDefinition` object must be present in the `<head>` section: ```html <script> window.SPXGCTemplateDefinition = { "description": "My Template", "playserver": "OVERLAY", "playlayer": "7", "webplayout": "7", "DataFields": [ // Field definitions ] }; </script> ``` ### 2. Data Access Templates receive data through the `spxData` object (for JSON format) or XML document (for XML format). **JSON format (default):** ```javascript var name = spxData.f0; // Access field f0 var title = spxData.f1; // Access field f1 ``` **XML format:** ```javascript var name = spxData.getElementsByTagName('f0')[0].textContent; var title = spxData.getElementsByTagName('f1')[0].textContent; ``` ## Folder Organization ### Recommended Structure ``` ASSETS/templates/ └── myCompany/ └── ProjectA/ ├── css/ │ └── styles.css ├── js/ │ └── animations.js ├── images/ │ └── logo.png └── Template1.html ``` ### Relative Paths Templates can reference files relative to the template location: ```html <!-- CSS from relative folder --> <link rel="stylesheet" href="./css/styles.css"> <!-- JavaScript from relative folder --> <script src="./js/animations.js"></script> <!-- Images from relative folder --> <img src="./images/logo.png"> ``` ### Global Assets Reference files from the global ASSETS folder: ```html <!-- Global media --> <img src="/media/images/bg/background.png"> <!-- Global video --> <video src="/media/video/intro.mp4"></video> ``` ## Template Lifecycle ### Initialization When a template loads: 1. HTML is parsed 2. CSS is applied 3. JavaScript executes 4. Data is injected via `spxData` 5. Template can initialize animations/effects ### Animation Phases For multi-step templates: 1. **Step 1** - Initial animation/display 2. **Step 2+** - Additional phases (triggered by Continue button) 3. **Out** - Exit animation (triggered by Stop) ### Example Lifecycle Handler ```javascript // Wait for SPX renderer to be ready if (window.top && window.top.spxRenderer) { window.top.spxRenderer.on('play', function() { // Template started playing startAnimation(); }); window.top.spxRenderer.on('stop', function() { // Template stopped stopAnimation(); }); window.top.spxRenderer.on('continue', function() { // Continue to next step nextStep(); }); } ``` ## Best Practices ### 1. Responsive Design Consider different output resolutions: ```css .container { width: 1920px; height: 1080px; /* Or use responsive units */ width: 100vw; height: 100vh; } ``` ### 2. Performance - Minimize DOM elements - Use CSS transforms for animations (GPU accelerated) - Optimize images and media - Avoid blocking JavaScript ### 3. Error Handling Handle missing data gracefully: ```javascript var name = spxData.f0 || 'Default Name'; var image = spxData.f1 || '/media/images/default.png'; ``` ### 4. Browser Compatibility SPX templates run in modern browsers. Test in: - Chrome/Edge (Chromium) - Firefox - Safari ### 5. Accessibility Consider accessibility when designing templates: - Sufficient color contrast - Readable font sizes - Clear visual hierarchy ## Template Examples ### Simple Lower Third ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> .lower-third { position: absolute; bottom: 100px; left: 50px; background: rgba(0,0,0,0.8); padding: 20px; color: white; } </style> <script> window.SPXGCTemplateDefinition = { "description": "Simple Lower Third", "playserver": "OVERLAY", "playlayer": "7", "webplayout": "7", "DataFields": [ { "field": "f0", "ftype": "textfield", "title": "Name", "value": "" }, { "field": "f1", "ftype": "textfield", "title": "Title", "value": "" } ] }; </script> </head> <body> <div class="lower-third"> <h2 id="name"></h2> <p id="title"></p> </div> <script> document.getElementById('name').textContent = spxData.f0 || ''; document.getElementById('title').textContent = spxData.f1 || ''; </script> </body> </html> ``` ## Template Definition >[!IMPORTANT] Each HTML template must have a `JSON data object` present in the HTML file's source code, within the HEAD section. The TemplateDefinition configures how a template is supposed to work within SPX: what kinds of controls are shown to the operator and how the graphic should playout, on which server and layer for instance. These values are template's defaults and can be changed in the Project Settings view after the template is added to the project. ## Placement Place the template definition as the last item within the `<head>` section of your HTML file: ```html <head> <!-- Other head content --> <script> window.SPXGCTemplateDefinition = { // Definition object here }; </script> </head> ``` ## Complete Example ```html <script> window.SPXGCTemplateDefinition = { "description": "Top left with icon", "playserver": "OVERLAY", "playchannel": "1", "playlayer": "7", "webplayout": "7", "steps" : "1", "out": "manual", "uicolor": "2", "dataformat": "json", "DataFields": [ { "ftype" : "instruction", "value" : "A example demo template definition. Learn what it does and make use of it's capabilities." }, { "field" : "f0", "ftype" : "textfield", "title" : "Info text", "value" : "" }, { "field": "f1", "ftype": "dropdown", "title": "Select logo scaling", "value": "0.3", "items": [ { "text": "Tiny logo", "value": "0.3" }, { "text": "Huge logo", "value": "1.2" } ] }, { "field" : "f2", "ftype" : "textarea", "title" : "Multiline field", "value" : "First line\nSecond line\n\nFourth one" }, { "ftype" : "divider" }, { "field": "f3", "ftype": "filelist", "title": "Choose background image from global ASSETS-folder", "assetfolder" : "/media/images/bg/" , "extension" : "png", "value": "/media/images/bg/checker.png", }, { "field": "f4", "ftype": "filelist", "title": "Choose CSS stylesheet from template's relative styles-folder", "assetfolder" : "./styles/" , "extension" : "css", "value": "./styles/defaultStyle.css", }, { "field": "f5", "ftype": "number", "title": "Rotation degrees", "value": "45", }, { "field": "f6", "ftype": "checkbox", "title": "Show logo", "value": "1", }, { "field": "f7", "ftype": "button", "title": "Click me", "descr": "Describe button function here", "fcall": "myCustomHello('world')" }, { "ftype": "spacer" }, { "field": "f8", "ftype": "color", "title": "Text color", "value": "rgba(255, 255, 255, 1.0)" } ] }; </script> ``` ## Required Properties Theoretically all properties are optional, but it's recommended most properties, especially playout layers, are carefully given to prevent clashes during playout. ### Playout Settings ### `playserver` One of the available CasparCG server names in config or `"-"` for none. ```json "playserver": "OVERLAY" ``` ### `playchannel` CasparCG playout channel number. ```json "playchannel": "1" ``` ### `playlayer` CasparCG playout layer (1-20, where 20 is frontmost). ```json "playlayer": "7" ``` > `Layer` is a number between 1..20. Layer 1 is at the very back and 20 is the highest ("closest to the camera"). Layers can be changed for each template in each project separately in the Project Settings. ### `webplayout` A number between 1..20 for web playout layer, or `"-"` for none. ```json "webplayout": "7" ``` ### `out` How layer should be taken out: - `manual` - Default way: press STOP to animate out - `none` - Play only. Suitable for wipes/bumpers - `[numeric]` - Milliseconds until STOP is executed automatically ```json "out": "manual" // or "out": "4000" // Auto-stop after 4 seconds ``` ### `steps` How many phases in animation? For normal in-out templates this is 1. For templates with 2 or more steps, the Continue button gets enabled. ```json "steps": "1" ``` ### `dataformat` How template logic is expecting data: - `json` - The default value (from 1.2.2) - `xml` - For compatibility with older CasparCG templates ```json "dataformat": "json" ``` ### Display Settings ### `description` Template name/description shown in SPX UI. ```json "description": "Top left with icon" ``` ### `uicolor` UI color theme for the template (1-7). ```json "uicolor": "2" ``` ## DataFields The `DataFields` array defines what input controls are shown to the operator when editing a rundown item. Each field has: - `field` - Unique identifier (e.g., "f0", "f1") - `ftype` - Field type (textfield, dropdown, etc.) - `title` - Label shown in UI - `value` - Default value See [[HTML#Field Types|Field Types]] for complete list of available field types. ### Field Order The values of the first two fields are used as content preview in the rundown, so the order of fields should be considered for ease of use. ## Accessing Field Values in Template In your template's JavaScript, access field values through the data object: ```javascript // For JSON dataformat (default) var fieldValue = spxData.f0; // For XML dataformat var fieldValue = spxData.getElementsByTagName('f0')[0].textContent; ``` ## Template Definition Best Practices 1. **Set appropriate layers** - Avoid conflicts with other templates 2. **Order fields logically** - First two fields appear in rundown preview 3. **Provide defaults** - Set sensible default values 4. **Use descriptive titles** - Help operators understand fields 5. **Document with instructions** - Use `instruction` field type for help text ## Field Types Field types (ftypes) define template's GUI controls in SPX controller. The values of the first two fields are used as content preview in the rundown, so the order of fields should be considered for ease of use. ## Available Field Types | Field Type | Description | Example | |------------|-------------|---------| | `hidden` | A variable which is not editable by the user. Value is used by the template and title shown as static text on UI. | `Red color (#f00)` | | `caption` | The value is shown in UI. Caption can be used to display texts to operators of the template. | `This template does not have editable values` | | `textfield` | A typical single line text input field. | `Firstname Lastname` | | `dropdown` | A dropdown selector list. Options is an items array. | See example below | | `textarea` | A multiline text control which accepts return key for new lines. (Added in 1.0.2) | `First line \n Second line` | | `filelist` | A dropdown selector list for files of given type extension in an assetfolder. (Added in 1.0.3) | See example below | | `divider` | A utility ftype to add a visual divider to a template. (Added in 1.0.3) | | | `instruction` | Value can be used as a longer help text on the template. (Added in 1.0.6) | `Max 100 characters to the field below.` | | `number` | Value is exposed as a number field in the template UI. (Added in 1.0.7) | `45` | | `checkbox` | Title is used as label in UI. Value is "0" or "1" when checked. (Added in 1.0.10) | `[x] Show logo` | | `color` | Title is used as label in UI. Value is a valid CSS color string. (Added in 1.1.1) | `rgba(255,255,255,1.0)` | | `spacer` | Just an empty line to separate out sections. (Added in 1.1.2) | `(no parameters)` | | `button` | A button that can trigger custom JavaScript functions. | See example below | ## Field Type Examples ### textfield Single-line text input: ```json { "field" : "f0", "ftype" : "textfield", "title" : "Name", "value" : "John Doe" } ``` ### textarea Multi-line text input: ```json { "field" : "f1", "ftype" : "textarea", "title" : "Description", "value" : "First line\nSecond line\n\nFourth one" } ``` ### dropdown Selection from a list of options: ```json { "field": "f2", "ftype": "dropdown", "title": "Select logo scaling", "value": "0.3", "items": [ { "text": "Tiny logo", "value": "0.3" }, { "text": "Huge logo", "value": "1.2" } ] } ``` > **Note:** The default selection is defined as `value` and it must be one of the values in the `items` array. ### filelist File picker from ASSETS folder: ```json { "field": "f3", "ftype": "filelist", "title": "Choose background image", "assetfolder": "/media/images/bg/", "extension": "png", "value": "/media/images/bg/checker.png" } ``` **Relative paths** (v1.0.15+): If `assetfolder` path value starts with `"./"`, the path is considered relative to the template root folder: ```json { "field": "f4", "ftype": "filelist", "title": "Choose CSS stylesheet", "assetfolder": "./styles/", "extension": "css", "value": "./styles/defaultStyle.css" } ``` ### number Numeric input: ```json { "field": "f5", "ftype": "number", "title": "Rotation degrees", "value": "45" } ``` ### checkbox Boolean checkbox: ```json { "field": "f6", "ftype": "checkbox", "title": "Show logo", "value": "1" } ``` Value is `"0"` when unchecked, `"1"` when checked. ### color Color picker: ```json { "field": "f8", "ftype": "color", "title": "Text color", "value": "rgba(255, 255, 255, 1.0)" } ``` Value must be a valid CSS color string such as: - `rgb(255,0,0)` - Full red - `rgba(0,0,0,0.33)` - Black with 33% opacity - `#ff0000` - Hex color > **Please note:** The Color Picker UI feels a bit flaky, color may need to be selected two or more times for it to register as intended. This may improve in future versions. ### button Custom button that triggers JavaScript: ```json { "field": "f7", "ftype": "button", "title": "Click me", "descr": "Describe button function here", "fcall": "myCustomHello('world')" } ``` The `fcall` property contains JavaScript code that will be executed when the button is clicked. ### instruction Help text displayed to operators: ```json { "ftype": "instruction", "value": "A example demo template definition. Learn what it does and make use of it's capabilities." } ``` ### divider Visual separator: ```json { "ftype": "divider" } ``` ### spacer Empty line for spacing: ```json { "ftype": "spacer" } ``` ### hidden Non-editable variable with static display: ```json { "field": "f9", "ftype": "hidden", "title": "Template version", "value": "1.0.0" } ``` ### caption Static text display: ```json { "ftype": "caption", "value": "This template does not have editable values" } ``` ## Project Variables Fields can reference project variables using the `prvar` property: ```json { "field": "f0", "ftype": "textfield", "title": "Name of the event", "value": "Fakemusic Fest 2022", "prvar": "eventName" } ``` When a field has `prvar`, it becomes a project variable that can be shared across multiple templates. See [[Documentation/Graphics Controller/Project Settings#Project Variables|Project Settings]] for more information. ## Field Order Best Practices 1. **Most important fields first** - First two fields appear in [[Documentation/Graphics Controller/Rundown Settings|rundown]] preview 2. **Group related fields** - Use dividers to separate sections 3. **Provide instructions** - Use instruction fields for complex templates 4. **Set sensible defaults** - Help operators with pre-filled values --- ## Read Next - [[Documentation/Graphic Templates/Formats/OGraf|OGraf Templates]] - EBU standard format - [[Documentation/Graphic Templates/Overview|Templates Overview]] - General templates information - [[Documentation/Graphics Controller/Project Settings|Project Settings]] - How to configure templates in projects - [[Documentation/Graphic Templates/Advanced/Scene and Transition Logic|Transition Logic]] - State-based graphics