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:
| Interface | Purpose | Wired in v0.1.0? |
|---|---|---|
math | Exposes new functions to the math expression engine | Yes |
kpiProcessor | Computes KPIs for a lap given its samples | Yes |
runPlan | Custom run-plan logic | typed only |
uiCell | Returns RFW JSON for a CID cell | typed only |
transform | Server-side data transforms | typed only |
liveHook | Reacts to real-time events | typed 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."
}
| Field | What it does |
|---|---|
id | Globally unique plugin id |
version | Semver. Plugin rows are keyed by (accountId, id, version) |
interfaces | Which of the six interfaces this plugin implements |
capabilities | Which host capabilities the plugin needs (fetch, storage, …). Currently log-only; UI for granting is queued |
publisher / description | Display 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
- Want to write one? → Writing a Plugin
- Want to bundle and upload? → Bundling and Uploading
- Want to understand capabilities? → Capabilities and Security
- Want to understand client vs server runtime? → Running on Client vs Server
What you can do today
- Author plugins implementing
mathandkpiProcessor - Bundle with the SDK's esbuild wrapper
- Upload via
pnpm seed:demo-pluginorPOST /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)