Bundle Widgets and Data Sources
A plugin can bundle ordinary Widgets and declarative Data Sources. A bundled module is the same module it would be at the repository root: the same manifest, the same conformance, the same runtime. Only its ownership differs. Installing the plugin makes its modules available for creation and playback. You can’t remove the plugin while saved content still uses its modules; see How removal treats bundled content.
Know the plugin ID
Section titled “Know the plugin ID”The plugin directory is a location. The id in tilecast.plugin.json is the identity. They can differ: plugins/emergency-alerts/ is owned by emergency_alerts. Every command below accepts either form and resolves it through the manifest, and every catalog entry records the manifest ID, never the directory name.
Bundle a Widget
Section titled “Bundle a Widget”Scaffold the Widget inside the plugin directory:
npm run widgets:new -- scoreboard --plugin athleticsThe result is an ordinary Widgets V2 Widget: tilecast.widget.json, a runtime entry point, and fixtures. No second Widget type exists, and Plugin API v1 does not change.
Data Source selectors inside a Widget’s repeating_group fields are followed for playback and dependency tracking, just like top-level selectors. See the Widget dependency contract for details.
Use the SDK’s announceReady, announceEmpty, and announceError helpers to report rendering state. Each input update gets a new readiness deadline. If rendering starts asynchronous work, capture widgetInputRevision(this) before starting and pass it to the announce helper when the work finishes. A result from an older revision is ignored. See the Widget lifecycle contract for the exact rules.
When your Widget declares a media_asset field, Tilecast resolves each selected asset before playback and gives the component the matching media grant. A key such as logoAssetId gets the derived key logoVariantId. Tilecast adds the variant inside each matching item when the field is inside a repeating group. The Studio preview uses the same field mapping. See the Widgets V2 engineering reference for the full key rule and manifest contract.
The Widget SDK exposes each Data Source dataset through WidgetResources. Dataset cache state, time zone, units and date-selection rules stay with that dataset in Data Document v1.
Studio Widget previews preserve the field types of connected Structured Data Sources, so developers see the same numbers, dates, and links that playback receives. The API contract describes the preview’s fieldSchema.
The Player applies dataset date-selection rules before it gives resources to a Widget. It uses the corrected Player clock, the policy time zone and the organization’s first day of the week. Compatibility Widgets use the same rules.
When no records match, last_known_good selects all records from the latest cached date before the requested day. For a tomorrow preview, that can include today’s records. The default empty policy keeps past records out. The native server preview and Player projection share the date-selection conformance corpus.
Describe how Studio edits the Widget
Section titled “Describe how Studio edits the Widget”Studio has one Widget editor, and your manifest drives it. You don’t write an editor. The configurationSchema is the inspector, and an optional authoring object adds hints for the preview.
- Labels. Write each field’s
label,description, and select options as plain text in your own language. That is all Studio needs. You don’t register anything in Tilecast’s translation files. - Translation keys.
labelKey,descriptionKey, and an option’slabelKeyare optional. They name strings in Tilecast’s owndefinitionsnamespace, which only the built-in Widgets use. A key that Studio can’t find shows your plain text instead, so a missing translation never leaves a control without a label. - Recommended frame. If your Widget is built for a shape, such as a strip, set
authoring.preview.recommendedFrameto awidthandheightin pixels, from 32 to 3840. Studio opens the preview at that size, draws the library thumbnail from it, and gives a new Layout placement the same shape. Nothing reaches the Player.
"authoring": { "preview": { "time": true, "recommendedFrame": { "width": 1920, "height": 200 } }}The Widget authoring contract has every control and hint.
Bundle a declarative Data Source
Section titled “Bundle a declarative Data Source”Scaffold the module inside the plugin directory:
npm run data-sources:new -- schedule --plugin athletics --adapter http_recordsThe adapter is one of manual_object, manual_records, or http_records. Those are the only adapters with a declarative binding. A module that needs OAuth, proprietary authentication, or domain workflows is executable code and belongs on plugin.DataSourceProvider instead; see Publish a Data Source or private asset.
The result is a tilecast.datasource.json manifest plus a fixtures/ sample configuration. The manifest carries no scripts, no SQL, and no credentials.
Check the contribution
Section titled “Check the contribution”Validate the whole plugin, including nested modules:
npm run plugins:checkRun the full Widget and Data Source conformance over the same directories:
npm run extensions:checkBoth commands fail when a generated file is stale. Regenerate with npm run extensions:generate and check again.
How removal treats bundled content
Section titled “How removal treats bundled content”Removing a plugin never deletes the content authors made from its modules. Removal is blocked while rows still use a contributed provider, with an entry such as 2 Data Sources and a delete resolution. Delete the rows through the library first, then remove the plugin.
A restored database can hold content from a plugin that isn’t installed. That content stays saved but unused: Tilecast doesn’t assign it, send it to screens, or refresh its data until you install the plugin again.
For the exact contracts, use the Widgets V2 engineering reference, the Data Source modules engineering reference, and the Plugin API v1 engineering reference.