Skip to content

Add server behavior

Server code lives in the plugin directory and imports the Go Plugin SDK. It must not import apps/server/internal.

Implement plugin.Initializer when the plugin needs Tilecast services:

func (p *Plugin) Init(_ context.Context, host plugin.Host) error {
p.host = host
p.db = host.DB
return nil
}

Host.DB is for the plugin’s own tables. Use the other Host services for core state.

Common services include Installation, Audit, Manifests, Targets, Takeovers, ManagedPresentations, BackgroundJobs, Screens, Organization, Clock, Logger, DataSources, Users, and PluginAssets.

If a plugin needs a core table that is not represented by a Host service, don’t query that table directly. Extend the API deliberately.

Implement plugin.RouteProvider and register routes below one of the manifest’s api.basePaths.

Choose the access level that matches the endpoint:

  • AccessViewer is for enrolled read-only GET and HEAD requests.
  • AccessManager requires Owner or Administrator and CSRF on mutations.
  • AccessSession requires an enrolled session and leaves resource-specific authorization to the plugin.

Use plugin.PrincipalFrom for the signed-in user and plugin.DecodeJSON for strict JSON requests.

Use HandleWithRateLimit with plugin.RateLimitOperations for an operation that needs the shared operations limiter.

Keep matching paths in api/openapi.yaml. plugins:generate composes the fragments into Tilecast’s canonical OpenAPI document.

StatusReporter supplies configured, active, instance-count, and attention state to the plugin catalog.

RemovalGuard runs inside the Remove transaction. Return blockers when the operator must delete, disable, or wait for plugin-owned resources before removing the installation row.

Removing an installation does not delete plugin data.

A WorkerProvider returns named workers. Automatic work should check the plugin installation and Host.BackgroundJobs.Allowed().

The second gate pauses background changes during backup and restore. An explicit operator action does not use that gate.

Emergency Alerts is the current example of a networked background worker.

Implement DemoSeeder when the plugin should add useful sample data to Demo Mode. Countdown Bar uses it to add a lunch countdown.

Keep demo seeding thin. It should use the same plugin behavior that normal product code uses.