NeoPiano modding

Create for NeoPiano

A community of pianists, a 3D engine and an API designed for creators. Build the learning tool, visual effect or game mode NeoPiano is missing, and share it.

What you can build

  • Learning tools

    Chord detector, visual metronome, scale exercises, playing statistics.

  • Note effects

    Trails, spheres, sparks and materials that react to pitch and velocity.

  • Native UI

    Dock panels, HUDs above the keyboard, dialogs, toasts and shortcuts.

  • Scenes and themes

    Full sets, lights and moods built in Unreal Engine 5.8.

  • Game modes

    Play together, NeoPiano’s online mode, is a mod like any other.

  • Creative MIDI

    Arpeggiators, accompaniment, harmonizers (in upcoming API versions).

The Play together mod: its settings panel blends into the NeoPiano interface

Play together is a mod: its panel, settings and notifications use the same components as NeoPiano.

Three ways to mod

Every function of the neo API exists in Lua, in WebAssembly and as a Blueprint node, with exactly the same powers. Pick the language you like, not the one with the most features.

  • Fastest start

    Lua 5.4

    One .lua file declared in the .uplugin, no Unreal editor, no compiling. Hot reload and autocompletion thanks to the bundled LuaLS annotations.

  • C and C++

    WebAssembly

    Compile your code with the provided script (wasi-sdk) into a .wasm of a few kilobytes. One file for Windows and macOS.

  • Unreal Engine 5.8

    Blueprint and content

    Build materials, Niagara, scenes and Blueprints in the Launcher UE 5.8 with the NeoPiano SDK, then cook your mod.

A mod in a few lines

This mod adds a dock panel with a toggle and counts the notes you play, keeping the total between sessions.

Mods/NoteCounter/NoteCounter.uplugin
{
  "FileVersion": 3,
  "FriendlyName": "Note Counter",
  "Version": 1,
  "VersionName": "1.0.0",
  "CanContainContent": false,
  "NeoModApiVersion": 5,
  "NeoModScripts": ["Code/NoteCounter.lua"],
  "NeoModCapabilities": ["ui.panel", "settings", "storage"]
}
Mods/NoteCounter/Code/NoteCounter.lua
-- NoteCounter.lua: counts your notes, even across sessions
local total = neo.storage.get("total", 0)

function on_mod_init()
  neo.settings.define({
    { id = "enabled", type = "toggle", label = "Count notes", default = true },
  })
  neo.ui.panel({
    id = "main", title = "Counter", icon = "piano",
    content = { type = "column", children = {
      { type = "label", id = "count", text = tostring(total) .. " notes" },
      { type = "button", id = "reset", text = "Reset" },
    } },
  })
end

function on_note_on(note, velocity)
  if not neo.settings.get("enabled") then return end
  total = total + 1
  neo.storage.set("total", total)
  neo.ui.set("count", "text", total .. " notes")
end

function on_ui(id, event, value)
  if id == "reset" and event == "click" then
    total = 0
    neo.storage.set("total", 0)
    neo.ui.set("count", "text", "0 notes")
    neo.ui.toast("Counter reset", "success")
  end
end

Safe for players, simple for you

  • Declared capabilities

    Your mod lists what it uses (ui.panel, storage…). Players see it before enabling, like browser extension permissions.

  • Shared budgets

    20 ms per call, 6 ms per frame shared across mods: no mod can make NeoPiano stutter.

  • Isolated failures

    An error, an infinite loop or too much memory: the mod is disabled with a clear reason, NeoPiano keeps going.

  • Debugging tools

    In-game mod log, CPU time and memory per mod, hot reload.

Ready to create?

The guide takes you from zero to a mod running inside NeoPiano.

The documentation is currently written in French.