Getting Started with Surfaces
So, you want to develop a surface module for Companion? Welcome!
A surface module teaches Companion how to talk to a physical control surface — reading button presses and encoder turns, and drawing button graphics, indicators and brightness onto the hardware. Surface modules are plugins, just like connection modules, and they are built with the same tooling and released through the same workflows.
Surface and connection modules share almost all of their development environment, repository tooling and release process. Rather than duplicate that here, this section links you to the relevant Connection Development pages and concentrates on what is genuinely different for surfaces. Connection modules are far more common, so if a topic isn't covered here, the connection docs are almost always the right place to look.
Prerequisites
Before you start, make sure you have installed the development tools and are comfortable with Git workflows. These are the same for all Companion module development.
Shared setup — reuse the connection docs
The following steps are identical for surface and connection modules. Follow the connection pages and come back here for the surface-specific API:
- Installing Companion and setting up the development folder
- Setting up a dev folder so Companion loads your module while you work
- Repository file structure
- The
manifest.jsonfile — note that surface modules declare some surface-specific fields; see Surface Plugin Overview - Module development 101 for the general build → release → maintain lifecycle
- Packaging and releasing a module
What's different for surfaces
Where a connection module defines actions, feedbacks and variables, a surface module implements
the SurfacePlugin interface and is responsible for:
- Discovering and connecting to surfaces
- Representing each connected surface
- Declaring the surface's physical layout
- Rendering the images Companion pushes, plus brightness and LEDs
- Reporting input events back to Companion
- Handling the lock screen / pincode entry
Read on in Surfaces: Basics.
Reference material
- Generated API reference: bitfocus.github.io/companion-surface-api
- companion-surface-api wiki
Existing modules are the best reference for a real, working implementation. Which one to look at depends on how your surface connects — there's no single "canonical" example because the discovery flows differ:
- USB (HID) and remote/network:
companion-surface-elgato-stream-deck(comprehensive, but a large codebase) - Serial port:
companion-surface-loupedeck
Questions? Reach out on Slack! :)