Universal Controller MIDI

Templates

Create a template from scratch

Build a Universal Controller MIDI template from an empty schema. Covers required fields, validation, and how to drop the file into your library.

Updated

Sometimes none of the 48 bundled mappings fit and customising one of them feels like fighting the file. Building a template from scratch is roughly ten minutes of typing, one validation pass, and a hot-reload. The schema is small and forgiving — you'll spend more time deciding what notes to use than wrestling the file format.

The minimum viable template

Every field on the schema has a default, so the smallest valid file is shorter than you'd expect. Save the JSON below as My Template.json in your user library folder and the app picks it up on next load. No buttons, no axes, but it loads — and you can wire it up in the UI from there.

{
  "name": "My Template",
  "schema_version": 2,
  "midi_channel": 0,
  "deadzone": 0.05,
  "poll_hz": 100,
  "buttons": {},
  "axes": {},
  "hats": {}
}

Drop the file into Settings → Reveal library while the app is running. Templates hot-reload — no restart needed. The status strip flashes green for a successful load, red with a message for a validation failure.

Field-by-field reference

Here's every top-level field, its type, and whether it's required. Use this as your scaffolding checklist:

FieldTypeRequiredNotes
namestringyesShown in the dropdown; under 50 chars
schema_versionintegeryesMust be 2 right now
midi_channel0–15noDefaults to 0
deadzone0.0–1.0noDefaults to 0.05
poll_hz30–250noDefaults to 100
buttonsobjectnoString-indexed button to MIDI note
axesobjectnoString-indexed axis to MIDI CC
hatsobjectnoNamed D-pad directions to MIDI notes
left_stick_cornersobjectnoDefaults to enabled: false
right_stick_cornersobjectnoSame shape as left
touchpadobjectnoenabled + x_cc + y_cc
oscobjectnoRoutes axes/buttons to OSC instead of MIDI
l2_haptic_effectstring|nullnoPS5 only
r2_haptic_effectstring|nullnoPS5 only

Filling in the meat

Work in this order to avoid getting lost:

  1. Buttons — keys are controller button indices ("0" through "16"), values are MIDI note numbers 0–127.
  2. Axes — same shape but values are MIDI CC numbers. Sticks and triggers route through this.
  3. Hats — D-pad. Four named keys: up, down, left, right.
  4. Stick corners — only if you want note grids from sticks (see stick corners).
  5. Touchpad / OSC / Haptics — optional sections. Set enabled: false if unused.

A complete-but-minimal mapping that actually does something interesting:

{
  "name": "Snare Roll Special",
  "schema_version": 2,
  "midi_channel": 1,
  "deadzone": 0.04,
  "poll_hz": 150,
  "buttons": { "0": 38, "1": 40, "2": 42, "3": 44 },
  "axes": { "4": 1, "5": 11 },
  "hats": { "up": 78, "down": 79, "left": 80, "right": 81 },
  "left_stick_corners": {
    "enabled": true,
    "n": 4,
    "notes": [60, 64, 67, 72],
    "r_enter": 0.9,
    "r_exit": 0.7
  },
  "l2_haptic_effect": "trigger_click",
  "r2_haptic_effect": null
}

Validation

The app validates on load and surfaces errors in the bottom status strip. The common ones:

  • schema_version missing or not 2 — template ignored.
  • MIDI note out of range — clamped silently to 0–127, but you'll see a warning.
  • Duplicate name — second one wins; rename to avoid surprises.
  • Invalid JSON — the template is skipped entirely; the rest of your library still loads.

JSON keys are strings even when they look like numbers. { "buttons": {0: 36} } is invalid — it must be { "buttons": { "0": 36 } }. Quote everything.

The schema is intentionally flat. No nesting beyond one level, no inheritance, no conditional layers. Flat schemas are easy to diff, easy to migrate, easy to validate. The trade-off — you can't share fragments between templates — is worth paying.

Real-world template patterns

  • Drum kit starter — 16 entries in buttons mapped to GM drum notes 36–51, no axes, no corners. Done in five minutes.
  • Pure-CC controller — empty buttons, 8 entries in axes tied to your favourite plugin's CCs. Hands stay on the sticks.
  • Single-stick melody — left stick corners at n: 16 with a chromatic octave, everything else disabled. Maximalist minimalism.
  • OSC-only template — empty MIDI sections, the osc block does all the work. Great for lighting consoles.
  • Hybrid podcast rig — face buttons fire stingers, touchpad is mic-mute toggle, sticks are ducker/EQ CCs.

Ship it

Happy with the mapping? Either keep it local, or share to the marketplace so the next person doesn't have to reinvent it. Need to fold in an existing controller export first? See import a .tsi file.

Edit this page on GitHub Updated
ESC

Type to search.