Core model: T1 = full Node process
The one idea that matters: evoX runs your T1 plugin as a separate, full Node.js process. That means:- You can use any npm library you want (
npm install obs-websocket-js ws node-fetch…). - You can connect to external services directly — WebSocket, HTTPS API, local port. evoX does not sit in between.
- The SDK only manages the host side: which event arrived (key pressed, knob rotated), what is shown on the key (title/image/state), settings and logs.
Project setup
manifest.json. Setting types are rich — secret, oauth, select, color, number, toggle, hotkey, url, path are supported:
Pattern 1 — WebSocket integration (OBS)
runtime.mjs: set up the connection on the first willAppear, send commands on keyDown, clean up on willDisappear.
ws://127.0.0.1 connection is made directly — T1 is full Node, so no SDK “network capability” is needed. (This is not the case in the public T2 sandbox; there the host-brokered network.fetch is used.)
Pattern 2 — API + OAuth (Twitch/Spotify style)
There are two ways:- Your own token management: T1 is full Node, so you can read the token from a
secretsetting and use it directly withfetch. - Host-brokered OAuth: With SDK
beginOAuth(provider)/getOAuthStatus(provider)you use evoX’s credential vault; the raw token never returns to your plugin, the host injects it into the request.
Key image — setImage (dynamic images such as album art)
Besides the title, you can draw a dynamic image on the key. Two formats:
setState(id, n).
Knob support
Declare the action with"controllers": ["Knob"] and listen to action.dialRotate / action.dialDown — ideal for continuous values such as volume/brightness.
Lifecycle and cleanup
- Set up the connection lazily on
willAppear; close it onplugin.stop. - If polling is needed, start it on
willAppearand stop it onwillDisappear; use exponential backoff on errors. - Wrap every handler in
try/catch; log the error withconsole.error(visible in the Developer window) and notify the user withshowError. - The host assigns identity: do not write to any context other than
event.context.bindingInstanceId; ignore anactionIdyou don’t recognize.
Next step
Test in your own evoX
Load the project from the Developer window, assign it to a key, reload and see the logs.
