Declaring the Surface Layout
Each device you open declares a layout (the surfaceLayout field
of registerProps). The layout tells Companion two things: the controls the device has and
where they sit on a grid, and the style each control needs drawn — a bitmap of a given size, a
background colour, and/or text.
A layout has two parts: a set of named style presets (one called default is required), and a
map of controls:
const myLayout = {
stylePresets: {
// Required. Used for any control that doesn't name its own preset.
default: {
bitmap: { w: 72, h: 72, format: 'rgb' },
},
// Optional extra presets, referenced by name from a control below.
encoder: {
text: true,
colors: 'hex',
},
},
controls: {
// Ids are typically "row/column". Companion maps these onto its button grid.
'0/0': { row: 0, column: 0 },
'0/1': { row: 0, column: 1 },
'0/2': { row: 0, column: 2, stylePreset: 'encoder' },
},
}
Style presets
A preset describes what Companion should produce for a control:
-
bitmap: { w, h, format }— request a rendered image of this pixel size.formatis one ofrgb,rgba,bgr,bgra(defaultrgb). This is what most button surfaces use. -
colors: 'hex' | 'rgb'— request a background colour instead of (or alongside) a bitmap, for buttons with a plain RGB backlight. -
leds: { segments, mode }— request colours for an addressable strip or ring of LEDs attached to the control, such as the ring around a Stream Deck Studio encoder. A gauge on the button drives these.segmentsis how many individually addressable LEDs there are, andmodeis how Companion maps the gauge onto them:'full-ring'— the LEDs form a complete circle, so the gauge is rendered faithfully (its angles, deadzone and colours are respected 1:1). Segment 0 is at 6 o'clock and indices increase clockwise.'simple'— any other shape, such as a straight strip. The value is swept across all the segments, with segment 0 as the 0% end.
Both describe a logical ordering; if your hardware is wired differently, re-map the segments locally. Check
supportsLedson the host capabilities first — when the host doesn't support LEDs, omitledsfrom your presets and fall back to whatever you'd otherwise draw (e.g. a plain backlight colour). -
text/textStyle— request button text (and text styling) for text-only displays.
Whatever you request here is what arrives in draw() — see Rendering. Get the
bitmap dimensions right: the resolution you declare is the resolution of the images you'll be
given.
Controls
Each control has a row and column (zero-based) and an optional stylePreset naming one of your
presets. The control id (the map key) should be unique and is typically row/column; it is the
controlId you'll see in draw and input calls.
The full schema (including pixel formats and style options) is in the generated reference. For a device that describes several different models, see the Elgato Stream Deck module.