Draw on the Player
A Player-facing plugin has two parts: the server projects manifest entries, and runtime/index.ts decides what to draw from those entries.
The shared Player Runtime also runs on Android. The Android application keeps its Kotlin shell and hosts the verified runtime bundle in a trusted WebView. A visual plugin can use one runtime/index.ts implementation across Electron, Tilecast Edge, and Android, while each Player still reports its supported capabilities. See the Player Runtime contract for the host boundary.
Project manifest entries
Section titled “Project manifest entries”Implement plugin.ManifestProjector on the server.
Each entry has a stable ID, a type declared in runtime.manifestTypes, a definition version, and plugin-owned configuration.
When configuration changes, use Host.Manifests to invalidate the affected screens through the normal manifest revision path.
Declare surfaces and a tier
Section titled “Declare surfaces and a tier”Available surface slots are strip.top, strip.bottom, the four corners, and overlay.
The tiers are emergency, live, scheduled, and ambient. A stronger tier wins a shared slot before priority is considered.
Emergency Alerts therefore wins the bottom strip over Countdown Bar.
Implement the runtime
Section titled “Implement the runtime”runtime/index.ts default-exports defineRuntimePlugin(...).
The runtime lifecycle has four main jobs:
mountcreates persistent elements inside the slot containers.updatereads manifest entries and returns the slots the plugin wants.renderupdates content from the slots the host granted.disposecleans up plugin-owned state.
The host owns arbitration, strip geometry, push and overlay insets, sleep and wake, reduced motion, and the corrected clock.
Use context.clock instead of unmanaged timers. Call context.invalidate() when state needs another evaluation.
Keep styles inside the plugin
Section titled “Keep styles inside the plugin”Put runtime styles in runtime/*.css. Every selector starts with the plugin scope, such as .tc-transit-alerts. Keyframe names use the same prefix.
plugins:check rejects styles that could reach another plugin or the Player itself.
Test time-dependent behavior
Section titled “Test time-dependent behavior”Use @tilecast/plugin-sdk/runtime/testing for a manual clock and deterministic runtime context.
Countdown Bar is the best current example of a scheduled surface with timers, offline evaluation, push geometry, and reduced-motion behavior.