Skip to content

Create a plugin

When you finish this page, you’ll have a plugin directory with a manifest, Go entry point, Studio page, public docs page, and conformance test.

Use a checkout that already passes the repository checks. Install the dependencies with make bootstrap.

  1. Choose a stable snake_case ID. It is stored in Tilecast data and should not change later.

  2. Run the scaffold command from the repository root:

    Repository root
    npm run plugins:new -- transit_alerts --name "Transit Alerts" --category Automation --api

    Omit --api if the plugin will not register HTTP routes.

  3. Open plugins/transit-alerts/tilecast.plugin.json and replace the generated description, icon, maintainers, requirements, and uses entries.

  4. Implement only the parts the plugin needs. A plugin that shows nothing on screens does not need Player projection; a plugin with no background work does not need a worker.

  5. Check the plugin:

    Repository root
    npm run plugins:check

The scaffold also regenerates the Go registry, CODEOWNERS, and composed API files.

plugin.go embeds the manifest and migrations and returns the server contribution. Put product logic under server/.

package transitalerts
import (
_ "embed"
"github.com/tilecast/tilecast/packages/plugin-sdk/go/plugin"
)
//go:embed tilecast.plugin.json
var manifest []byte
func New() plugin.Plugin {
return &Plugin{Bundle: plugin.NewBundle(manifest, nil)}
}

The scaffold creates a matching conformance test. Keep it.

You should not need to add the plugin ID to Tilecast Server startup, Studio routing, or the Player runtime. Those paths use generated registries or build-time discovery. The docs sidebar doesn’t list plugin pages, so a plugin that publishes a docs page links it from the plugin catalog page instead.

If the plugin needs a core fact that no Host service exposes, treat that as a Plugin API design change instead of reading a core table directly.

Next, read Write the plugin manifest, then use the server, Studio, or Player pages only for the parts your plugin needs.