Nodos Plugins: The Real-Time Graph That Refuses to Sleep
How a schema-driven plugin system, GPU-first execution, and always-dirty nodes turn Nodos into a live media engine instead of a static dependency graph.
- Nodos treats execution as a contract, not just a dependency graph, because some nodes must run every frame to keep live media responsive.
- The plugin repo reads like a standard library for a real-time engine, bundling animation, compositing, filters, and control flow behind one discovery layer.
- FlatBuffers schemas make node data portable across editor and runtime, which keeps the system disciplined as it grows.
- The result is less like a plugin pack and more like infrastructure for broadcast, motion graphics, and interactive pipelines.
The graph that cannot go idle
A normal reactive graph waits for change. Nodos cannot always afford to wait. Some nodes have to wake up every frame even when nothing upstream moved, because time, input, GPU state, and streaming media do not politely stop for dependency checks.
That is the point of the AlwaysDirty idea. It says some parts of the graph are not event handlers. They are part of the engine’s heartbeat. Without them, clocks stall, animations freeze, live sources drift, and frame history goes stale.
| Model | Execution model | Discovery | Schema enforcement | GPU integration | Best suited for |
|---|---|---|---|---|---|
| Reactive graph | Runs only when dependencies change | Usually hard-coded or local | Loose or optional | Often secondary | Dataflow that can sleep |
| Generic plugin folder | Extends a host app by convention | Manual registration or scanning | Minimal | Dependent on host | Simple extension ecosystems |
| Nodos plugins | Mixes reactive and always-dirty execution | Runtime plugin export contract | FlatBuffers-backed | Central to the design | Live media, compositing, and interactive graphics |
What lives in the plugin standard library
The repository is organized less like a grab bag and more like a toolkit. nosAnimation handles time and interpolation. nosCompositing handles layers and layouts. nosFilters covers image processing. nosFlow handles control flow. nosExperiment is where the team pushes on the edges.
| Plugin area | What it contributes | Why it matters |
|---|---|---|
| nosAnimation | Keyframes, interpolation, timing behavior | Keeps motion consistent across frames |
| nosCompositing | Layering, layout, text rendering | Turns raw assets into a usable scene graph |
| nosFilters | Blur, correction, temporal effects | Makes GPU processing feel like a first-class feature |
| nosFlow | Loops, triggers, conditional execution | Lets the graph act like a program, not just a pipeline |
| nosExperiment | Prototype and stress-test nodes | Provides room for the runtime to evolve |
How a node becomes executable
The plugin entrypoint is a contract. A plugin exports its node functions through nosExportPlugin, and those functions are registered with helpers such as RegisterAnimate. The engine does not need to know the plugin’s private structure. It only needs the exported shape.
The main idea of Nodos is to provide a complete, opinionated solution for building web applications, without the need to make hundreds of decisions about libraries and architecture.
The schema-first trick
The discipline comes from the schemas. Node and pin data live in .fbs FlatBuffers files, which makes the contract explicit and portable. Editor, runtime, and serialization all speak the same shape.
That matters more than it sounds. A visual engine gets messy fast when UI definitions, runtime code, and persistent data drift apart. Schema-first design reduces that drift. It also makes refactoring safer because the shape of a node is not hidden inside one language boundary.
| Approach | Where node shape lives | What tends to break | Long-term effect |
|---|---|---|---|
| Ad hoc C++ structs | In implementation files | Editor and runtime slowly diverge | Tight coupling, brittle evolution |
| Schema-first FlatBuffers | In shared .fbs definitions | Compiler catches mismatches earlier | Stable contracts across tools |
| Loose JSON conventions | In docs and implicit code paths | Serialization edge cases | Easy to start, hard to trust |
GPU state, time, and frames in motion
Two files make the runtime philosophy visible. AnimateNode turns elapsed time into normalized motion, with support for swing looping and variable step timing. TemporalBlurNode keeps frame history alive and updates texture formats when the input changes.
// Conceptual shape of the execution
float t = elapsedSeconds / duration;
if (swing) {
t = pingPong(t);
}
if (variableStepTiming) {
t = smoothWithFrameDelta(t, deltaTime);
}
history.push_back(currentFrame);
if (inputResolutionChanged) {
UpdateTextureFormat();
}
nosVulkan->RunPass(TemporalBlurShader, history);
This is where the repo stops looking like a plugin directory and starts looking like infrastructure. It is not just describing effects. It is preserving state, timing, and GPU continuity under live conditions.
Generating illustration...
Why this feels like infrastructure, not a plugin pack
A lot of plugin systems are permissive. This one is opinionated. It assumes a serious runtime, a specific execution model, and a team willing to encode stability into the architecture instead of patching it later.
That is why the repo feels mature. The refactoring breadcrumbs, the compatibility-minded naming, the split between shared types and plugin logic, and the emphasis on GPU-aware execution all point to the same thing: this is not a demo architecture. It is the scaffolding for live production work.
| Question | Ordinary extension system | Nodos plugins |
|---|---|---|
| Does the engine keep time itself? | Not necessarily | Yes, through always-dirty execution |
| Can plugins be discovered cleanly? | Sometimes, by convention | Yes, through a formal export contract |
| Do data shapes stay consistent? | Only if developers stay careful | Yes, through shared schemas |
| Does GPU state matter? | Often treated as downstream detail | It is part of the core design |





