Route Graphics is built around plugin groups registered in init(...):
plugins.elementsplugins.animationsplugins.audioElement plugins are the main extension point. They own parsing plus add/update/delete behavior for a single node type.
import { createElementPlugin } from "route-graphics";
export const badgePlugin = createElementPlugin({
type: "badge",
parse: ({ state }) => ({
...state,
x: Math.round(state.x ?? 0),
y: Math.round(state.y ?? 0),
width: Math.round(state.width ?? 120),
height: Math.round(state.height ?? 36),
label: String(state.label ?? ""),
}),
add: ({ parent, element }) => {
// create Pixi display object and add it to parent
},
update: ({ parent, prevElement, nextElement }) => {
// update existing display object
},
delete: ({ parent, element }) => {
// remove and destroy existing display object
},
});
Register it during init:
await app.init({
width: 1280,
height: 720,
plugins: {
elements: [textPlugin, badgePlugin],
animations: [tweenPlugin],
audio: [soundPlugin],
},
});
Audio plugins follow the same lifecycle idea for audio[] nodes:
typeaddupdatedeleteUse createAudioPlugin(...) when you want a custom sound source or scheduling strategy beyond the built-in sound node.
createAnimationPlugin(...) currently registers an animation type so the runtime accepts that animation family. The built-in tween plugin is the reference implementation. In practice, most custom behavior today is built through element and audio plugins.
parse(...) deterministic. It should normalize shape, not perform side effects.id as the stable lookup key for updates.eventHandler instead of hidden globals.