Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Browser Remote: Companion bridge for any website (via Tampermonkey)

This repository provides a generic remote-control bridge between Bitfocus Companion and any web app, using:

  • A local WebSocket server (Companion module) that dynamically renders actions, variables, presets, and image feedbacks
  • Per-site Tampermonkey userscripts that adapt a website’s UI/DOM/API to Companion

It lets you build integrations for sites without public APIs (e.g., Spotify, Google Slides, LiveU, Royalcast) using simple JavaScript.


How it works (end-to-end)

  1. A Tampermonkey userscript runs on a target page.
  • It opens a WebSocket to the local Companion module: ws://<host>:<port> or wss://<host>:(port+1).
  • On connect, it sends a “register” payload describing its capabilities:
    • Actions (things Companion can trigger)
    • Variables (values Companion can read)
    • Presets (ready-made buttons)
  1. The Companion module generates Companion UI dynamically.
  • Actions, variables, presets, and image feedbacks are created from the registry.
  • No hard-coded per-site schemas in the module.
  1. You press a button in Companion → Companion sends invoke to the correct tab.
  • The userscript calls DOM methods (e.g., .click()), sets inputs, or performs fetch in the page.
  1. When page state changes → userscript sends variableUpdate back to Companion.
  • Variables update live; presets and feedbacks react immediately.

Repository layout

  • clients/
    • template.js: minimal starter template for new adapters (simple actions/variables)
    • picker.js: advanced template with an in-page widget (status, host/port, logs) and an element picker to create watchers (variables) and click actions dynamically
    • spotify.js, googleslides.js, liveu.js, royalcast.js, flowics.js: examples of real integrations
  • companion-module-websocket-server/ (Companion module)
    • src/main.ts: WebSocket server + dynamic Companion layer
    • src/config.ts: module config (host/port, UUID handling)

Quick start

  1. Install Bitfocus Companion and load this module
  • Build the module:
    • In companion-module-websocket-server/ install deps (yarn or npm)
    • Build: yarn build (or npm run build)
  • Start the module in Companion
  1. Install a userscript in your browser
  • Install Tampermonkey
  • Create a new userscript and paste the contents of one of the files in clients/
    • For a clean start: use clients/template.js
    • For rapid prototyping with an on-page picker: use clients/picker.js
    • Update the @match to your target site
  1. Open the target site and connect
  • Userscripts connect to ws://127.0.0.1:3000 by default
  • The module also exposes WSS on (port+1) with a self-signed cert (no files required)
    • Example: wss://127.0.0.1:3001
  • If you use picker.js, use the top-right widget to select ws/wss, host and port, and see logs

The registry contract

On connect, send a register message:

{
  "type": "register",
  "registry": {
    "uuid": "0000",
    "source": { "site": "Spotify", "title": "Window Title" },
    "actions": {
      "play": { "name": "Play", "parameters": { "type": "object" } }
    },
    "variables": {
      "songTitle": { "name": "Song Title", "type": "string", "value": "" }
    },
    "presets": {
      "play_btn": { "name": "Play", "action": "play" }
    }
  }
}

Send variable updates as:

{
  "type": "variableUpdate",
  "uuid": "0000",
  "values": { "songTitle": "My Track" }
}

The module namespaces variables internally as ${uuid}_${varKey} and actions as ${uuid}__<site>__${actionKey}.


UUIDs and tab scoping

  • Each userscript creates a short tab id: first 4 chars of a UUID (e.g., 0000)
  • Config option “Treat all clients as one (ignore UUIDs from tabs)” creates a logical client id per site (e.g., default_spotify), while still routing invokes with the original short id
  • In presets, use {{uuid}} inside text to get the active id without hardcoding

Images: generic “Image Background” feedbacks

If a variable ends with Url or Png64, the module auto-adds a feedback that sets a button background:

  • *Url: fetched and cached to PNG64
  • *Png64: used directly

Examples:

  • Spotify albumArtUrl → “Image Background – Album Art URL”
  • Google Slides gsSlideCurrPng64 → “Image Background – Current Slide (PNG64)”

Templates and examples

  • clients/template.js (minimal): connect, one action, one variable, handle invoke
  • clients/picker.js (advanced): widget + picker to create watchers (variables) and click actions; persists to localStorage
  • clients/googleslides.js: presenter popout hook + dom-to-image
  • clients/spotify.js: DOM observers, presets with variables, volume up/down
  • clients/liveu.js: per-unit variables and modem details with rate-limited polling

Best practices

  • ≤ 1 request/second per site
  • Use tokens from storage and page fetch when possible to avoid CORS
  • Keep TAB_UUID to 4 chars in labels
  • Wrap DOM/fetch in try/catch; change-detect before sending updates

Troubleshooting

  • Variables blank: ensure register is sent before updates; verify connection; reload after toggling ignore-UUID setting
  • Image not showing: variable must end with Url or Png64; for Url, the image must be publicly fetchable
  • Use WSS: wss://<host>:(port+1) – self-signed cert generated in memory

Contributing new adapters

  1. Copy clients/template.jsclients/<yoursite>.js and set @match
  2. Register one action and one variable
  3. Observe or poll the DOM; send variableUpdate when values change
  4. Add presets (text can include variables; attach image feedbacks)
  5. For discovery, use clients/picker.js to create watchers and clickers quickly

License

MIT. Example scripts are provided as-is.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages