Color Palettes
The palette exists for one reason: during a performance you don’t want to hunt through parameter panels to change colours. One click on a swatch swatch palette One colour in the palette. Seven per set by default. should recolour every source that ought to recolour. That’s what the palette does.
Seven swatches, one per set
Each performance set performance set performance A named cue in your show. Each set has its own chain, modulations, palette, and bindings. Learn more → has its own palette. A palette is a list of swatches (defaulting to seven), a per-node channel assignment table, and a master hue offset master hue offset palette Shifts every swatch's hue at once. Modulate to slowly rotate the whole palette through the colour wheel. . All three are part of the set’s saved state, so switching sets switches colour schemes along with chains and modulations.
A swatch is just a single colour in HSB (hue, saturation, brightness) — not HSL or RGB. The defaults ship as a rainbow spread across the hue wheel at high saturation and full brightness: red, orange, yellow, green, blue, purple, pink.
There’s nothing special about the count. Seven is just the default and a comfortable number for live use; the underlying data model supports any number of swatches.
Advanced — the swatch type
interface PaletteSwatch { h: number // hue [0, 1] s: number // saturation [0, 1] b: number // brightness [0, 1]}Colour groups and roles are what make binding possible
Every colour-related slider in Lightbridge — foreground hue, background saturation, second-colour brightness, and so on — is tagged with two pieces of information:
- What kind of colour it represents on its source. A source might have a “main colour,” a “background colour,” and a “second colour” — each is a separate group.
- Which HSB component it is — hue, saturation, or brightness.
That pair is what lets the palette do its job. When you bind the “main colour” group of a source to swatch 3, the palette knows to push the swatch’s hue into the source’s hue slider, the swatch’s saturation into the saturation slider, and the brightness into the brightness slider — all together.
This is why one click on a swatch can recolour every source that ought to recolour: the binding system understands that “the main colour of source A” and “the main colour of source B” are conceptually the same thing if both are bound to the same swatch.
Advanced — colour group and role metadata
The two pieces of metadata are stored as fields on the source’s ParamDef:
colorGroup— a semantic name likecolor,bg,color1,color2,tint. Params that share acolorGroupbelong to the same conceptual colour on that source.colorRole— which HSB component the param represents. Exactly one ofh,s, orb.
A source with a single foreground colour uses color_h, color_s, color_b with colorGroup: 'color'. A source with foreground and background uses color_* and bg_*. A source with two foregrounds uses color1_* and color2_*. The full naming standard is documented in Parameter Conventions.
Channel assignments live per-node
A channel assignment is the binding between one of a source’s colour groups and a palette swatch. Each source on the chain remembers its own assignments, separately from every other source.
So you might have a Voronoi source on the chain whose main colour is bound to swatch 2 and whose background is bound to swatch 5. A Plasma source next to it might have its main colour also bound to swatch 2 (so they share that colour) and its background unbound (so the palette ignores it and Plasma uses whatever the slider says).
Any colour group that isn’t assigned to a swatch is simply off — the palette skips it and the underlying slider values get used as-is. This is what gives you fine-grained control: bind the colours you want unified, leave the rest free.
Advanced — channel assignment data shape
Channel assignments are stored as nested records keyed first by node ID, then by colour group name:
type PaletteChannels = Record<string, number> // colorGroup → swatch indextype PaletteConfig['channels'] = Record<string, PaletteChannels> // nodeId → assignmentsAbsent keys and -1 values both mean “off.”
The palette substitutes colours at render time
Crucially, the palette doesn’t mutate your stored slider values. When you click a swatch, the slider doesn’t visibly move — but the rendered output uses the swatch’s colour anyway. The substitution happens in the render loop, and the original slider value is preserved underneath.
This is why you can unbind a parameter from the palette and instantly get back the colour you had set on the slider before binding. The slider was always there, it just wasn’t being used.
Advanced — overlay pass details
Palette substitution is implemented as an overlay pass in the render loop:
store → palette overlay → modulation overlay → MIDI write → renderThe overlay walks every node in the chain, looks up its channel assignments, iterates the node’s param defs to find anything with a colorGroup that has a binding, and substitutes the swatch’s h, s, or b (based on colorRole) into the param value. The master hueOffset is applied additively to every swatch hue and wraps modulo 1.
Two performance details:
- Fast path — if no nodes have any channel bindings, the overlay returns the original array reference immediately and the whole pass is zero-cost.
- Structural sharing — if the overlay runs but nothing actually changed (delta <
1e-5), it still returns the original reference. Downstream code uses===to detect “no palette change this frame” and skips work.
Both of these matter for the 60 Hz render loop — the overlay runs every frame.
Palette in the priority chain
Palette is the middle layer in the parameter priority chain parameter priority general Which layer wins when MIDI, modulation, palette, and slider all try to set a parameter. Learn more → :
MIDI → Modulation → Palette → Slider → DefaultIn practice this means:
- A slider on a palette-bound colour parameter is overridden by the swatch. Dragging the slider updates the stored value, but that value isn’t what gets rendered.
- A modulation modulation modulation Drives a parameter automatically. Overrides the palette when both are bound to the same colour. Learn more → on a palette-bound colour parameter overrides the swatch. Binding the kick band kick band audio The bass drum frequency range. One of six bands Lightbridge splits your audio into. Learn more → to a hue parameter overrides the palette swatch for that parameter.
- A MIDI binding MIDI binding midi A physical knob, fader, or pad wired to a parameter. Once bound, it wins over everything else. Learn more → on a palette-bound colour parameter overrides everything — the palette skips any parameter MIDI is actively controlling.
This layering gives you three levels of control that don’t fight: static looks via the palette, energy via modulation, hands-on nuance via MIDI. None of them have to be torn down to add another.
Modulating the palette itself
The master hue offset is a normal numeric parameter, which means you can modulate it like any other. Dropping a slow LFO on the hue offset makes the entire palette rotate through the colour wheel — every bound swatch shifts together, keeping their relative hues. It’s a one-line trick that gives you evolving colour across a full show without fighting anything else.
Presets
A palette preset stores just the swatch list (not the channel assignments or hue offset). Saving a preset captures the colours of your current palette; loading one overwrites the swatches with the preset’s values. Channel assignments don’t change — so loading a new preset recolours all your bound params without losing any of the binding work you did.
Presets are stored alongside the show file and are available across all sets and all projects.
Where to go from here
- Colour Palette guide — hands-on: setting up bindings, editing swatches, building a preset library.
- Parameter Priority — exactly where palette sits relative to MIDI, modulation, and sliders.
- Performing Live — how palette swaps fit into a gig workflow alongside hold mode and sets.