Skip to main content

Plugins Overview

Race Platform plugins are TypeScript bundles that extend the platform's behaviour. The same bundle runs identically:

  • On the client via flutter_js (QuickJS) — in v0.1.0 this is scaffolded but the server adapter is used by default
  • On the server via Node V8 isolates (locally) / Cloudflare Workers V8 isolates (production)

Authoring a plugin uses the @race/plugin-sdk package (in packages/plugin-sdk/).

The six interfaces

A plugin's index.ts can export any combination of:

InterfacePurposeWired in v0.1.0?
mathExposes new functions to the math expression engineYes
kpiProcessorComputes KPIs for a lap given its samplesYes
runPlanCustom run-plan logictyped only
uiCellReturns RFW JSON for a CID celltyped only
transformServer-side data transformstyped only
liveHookReacts to real-time eventstyped only

The four typed-only interfaces have SDK types but no host wiring yet. They'll land as we extend the host.

The manifest

Every plugin ships a plugin.json:

{
"id": "race-demo:rolling-avg-rpm",
"version": "1.0.0",
"interfaces": ["math", "kpiProcessor"],
"capabilities": [],
"publisher": "Race Demo",
"description": "Rolling-average engine RPM math fn + KPI."
}
FieldWhat it does
idGlobally unique plugin id
versionSemver. Plugin rows are keyed by (accountId, id, version)
interfacesWhich of the six interfaces this plugin implements
capabilitiesWhich host capabilities the plugin needs (fetch, storage, …). Currently log-only; UI for granting is queued
publisher / descriptionDisplay metadata

The PluginValue type

All inputs and outputs between the host and plugin are typed as a sealed PluginValue union:

type PluginValue =
| { kind: "number"; value: number }
| { kind: "text"; value: string }
| { kind: "duration"; valueMs: number }
| { kind: "error"; message: string };

Lists are encoded as JSON-in-text — see the example in Writing a Plugin.

Where to go next

What you can do today

  • Author plugins implementing math and kpiProcessor
  • Bundle with the SDK's esbuild wrapper
  • Upload via pnpm seed:demo-plugin or POST /plugins/upload
  • Invoke via the Plugin Runner UI or POST /plugins/:id/invoke/{math,kpi}

What's coming

  • The other four interfaces (runPlan, uiCell, transform, liveHook)
  • Capability enforcement (today: log-only warning when an ungranted capability is requested)
  • Native client-side execution via flutter_js (scaffolded)
  • Plugin marketplace + signing + capability prompts (Phase 5)