A high-performance, extensible node-based editor built with Rust and gpui. Designed for building visual programming tools, workflow editors, and graph-based UIs.
This project is in early stage (alpha), API may change
https://github.com/user-attachments/assets/1d275e79-fcbf-4a4e-aba5-a1e3f3ff6029
crates/core - FerrumFlow editor core (graph model, plugins, interaction, rendering contracts)crates/sync_plugin - Yrs-based collaboration plugin (sync, awareness, multi-user workflows)[dependencies]
gpui = "0.2.2"
serde_json = "1.0"
ferrum-flow = { git = "https://github.com/tu6ge/ferrum-flow", branch = "master" }
This is a hello world example:
use ferrum_flow::{FlowCanvas, Graph};
use gpui::{AppContext as _, Application, WindowOptions};
use serde_json::json;
fn main() {
Application::new().run(|cx| {
let graph = Graph::build(|g| {
g.create_node("default")
.position(100.0, 100.0)
.data(json!({ "label": "Hello World" }))
.build();
});
cx.open_window(WindowOptions::default(), |window, cx| {
cx.new(|ctx| {
FlowCanvas::builder(graph, ctx, window)
.default_plugins()
.build()
})
})
.unwrap();
});
}
For more examples, see the examples directory.
Architecture details have moved to:
This includes core concepts, plugin/interaction/command model, node rendering contract, graph model, and performance/design principles.
We want an explicit, maintained view of supported vs partial vs missing relative to React Flow’s documented capabilities (nodes, edges, handles, selection, keyboard, minimap, controls, snapping, grouping/subflows, accessibility, etc.):
docs/react-flow-parity.md if it grows large).port_type of Port struct to custom enum type.Current mapping snapshot (as of this README update):
| React Flow capability | FerrumFlow mapping | Status | Notes |
|---|---|---|---|
| Canvas / viewport (zoom, pan, fit, controls) | Plugin: ViewportPlugin, ZoomControlsPlugin, FitAllPlugin; Core: Viewport | done/partial | Core zoom/pan done; behavior parity tuning ongoing. |
| Nodes (custom node UI, drag, multi-select drag) | Plugin: NodePlugin, NodeInteractionPlugin, SelectionPlugin; Core graph: Node | done | |
| Handles/ports (typed endpoints, connectability rules) | Plugin: PortInteractionPlugin; Core graph: Port, PortType | done/partial | Typed ports and validator path exist; full RF handle-option parity not complete. |
| Edges (rendering, interaction, visibility) | Plugin: EdgePlugin; Core graph: Edge | done/partial | |
| Selection (box select, additive selection, select-all viewport) | Plugin: SelectionPlugin, SelectAllViewportPlugin; Core selected sets | done | |
| Delete / keyboard editing | Plugin: DeletePlugin, HistoryPlugin; Command system | done | |
| Undo/redo command stack | Core: canvas::undo, Command, LocalHistory; Plugin: HistoryPlugin | done | |
| Clipboard copy/paste | Plugin: ClipboardPlugin | done/partial | Core flow present; parity on all RF clipboard scenarios not fully audited. |
| Minimap | Plugin: MinimapPlugin | done | |
| Context menu / node creation UX | Plugin: ContextMenuPlugin | done/partial | |
| Alignment / layout helpers / focus selection | Plugin: AlignPlugin, FocusSelectionPlugin | done/partial | |
| Background grid / viewport frame / chrome | Plugin: BackgroundPlugin, ViewportFramePlugin | done | |
| Subflows / parent-child grouping | N/A by design (currently) | missing/different by design | No explicit parent node/group graph model yet. |
| Accessibility API parity (ARIA, keyboard nav parity) | N/A (currently) | partial/missing | |
| Devtools-style state inspector parity | N/A (currently) | missing | |
| Collaboration / multi-user awareness | Plugin: sync_plugin (Yrs + awareness) | different by design (done) | Implemented via plugin architecture, not RF-style built-in surface. |
FerrumFlow is not only targeting parity. Some capabilities are intentionally stronger or more explicit than typical React Flow usage patterns:
Command interop guarantees (execute / undo / to_ops consistency)
The Command pipeline is designed so local execution, undo/redo, and operation replay can be tested for equivalence (command_interop), reducing divergence bugs.
Plugin-first architecture across behavior and rendering
Core editor capabilities (selection, viewport, minimap, clipboard, context menu, alignment, collaboration) are modeled as plugins instead of hardcoded monolith behavior.
CRDT collaboration as a first-class extension path
sync_plugin integrates Yrs awareness + graph ops, giving a concrete multi-user architecture beyond single-user canvas editing.
Clear separation of graph model, interaction lifecycle, and rendering
Graph / Viewport / Interaction / PluginContext boundaries are explicit, making it easier to evolve editor features without coupling everything into UI callbacks.
Rust-native integration potential
FerrumFlow can align with native Rust systems (state machines, persistence, sync backends, tooling) without requiring a browser-first runtime assumption.
Contributions welcome: propose a matrix in an issue or open a PR that extends this section.
Foundation work that unlocks most other extensions:
Node / Port private in the next release after migration APIs settle.No active schedule; keep these in mind when designing APIs above.
Contributions are welcome!
Feel free to open issues or PRs for:
Apache2.0
621 commits
Rust
100.0%
A high-performance, extensible node-based editor built with Rust and gpui. Designed for building visual programming tools, workflow editors, and graph-based UIs.
This project is in early stage (alpha), API may change
https://github.com/user-attachments/assets/1d275e79-fcbf-4a4e-aba5-a1e3f3ff6029
crates/core - FerrumFlow editor core (graph model, plugins, interaction, rendering contracts)crates/sync_plugin - Yrs-based collaboration plugin (sync, awareness, multi-user workflows)[dependencies]
gpui = "0.2.2"
serde_json = "1.0"
ferrum-flow = { git = "https://github.com/tu6ge/ferrum-flow", branch = "master" }
This is a hello world example:
use ferrum_flow::{FlowCanvas, Graph};
use gpui::{AppContext as _, Application, WindowOptions};
use serde_json::json;
fn main() {
Application::new().run(|cx| {
let graph = Graph::build(|g| {
g.create_node("default")
.position(100.0, 100.0)
.data(json!({ "label": "Hello World" }))
.build();
});
cx.open_window(WindowOptions::default(), |window, cx| {
cx.new(|ctx| {
FlowCanvas::builder(graph, ctx, window)
.default_plugins()
.build()
})
})
.unwrap();
});
}
For more examples, see the examples directory.
Architecture details have moved to:
This includes core concepts, plugin/interaction/command model, node rendering contract, graph model, and performance/design principles.
We want an explicit, maintained view of supported vs partial vs missing relative to React Flow’s documented capabilities (nodes, edges, handles, selection, keyboard, minimap, controls, snapping, grouping/subflows, accessibility, etc.):
docs/react-flow-parity.md if it grows large).port_type of Port struct to custom enum type.Current mapping snapshot (as of this README update):
| React Flow capability | FerrumFlow mapping | Status | Notes |
|---|---|---|---|
| Canvas / viewport (zoom, pan, fit, controls) | Plugin: ViewportPlugin, ZoomControlsPlugin, FitAllPlugin; Core: Viewport | done/partial | Core zoom/pan done; behavior parity tuning ongoing. |
| Nodes (custom node UI, drag, multi-select drag) | Plugin: NodePlugin, NodeInteractionPlugin, SelectionPlugin; Core graph: Node | done | |
| Handles/ports (typed endpoints, connectability rules) | Plugin: PortInteractionPlugin; Core graph: Port, PortType | done/partial | Typed ports and validator path exist; full RF handle-option parity not complete. |
| Edges (rendering, interaction, visibility) | Plugin: EdgePlugin; Core graph: Edge | done/partial | |
| Selection (box select, additive selection, select-all viewport) | Plugin: SelectionPlugin, SelectAllViewportPlugin; Core selected sets | done | |
| Delete / keyboard editing | Plugin: DeletePlugin, HistoryPlugin; Command system | done | |
| Undo/redo command stack | Core: canvas::undo, Command, LocalHistory; Plugin: HistoryPlugin | done | |
| Clipboard copy/paste | Plugin: ClipboardPlugin | done/partial | Core flow present; parity on all RF clipboard scenarios not fully audited. |
| Minimap | Plugin: MinimapPlugin | done | |
| Context menu / node creation UX | Plugin: ContextMenuPlugin | done/partial | |
| Alignment / layout helpers / focus selection | Plugin: AlignPlugin, FocusSelectionPlugin | done/partial | |
| Background grid / viewport frame / chrome | Plugin: BackgroundPlugin, ViewportFramePlugin | done | |
| Subflows / parent-child grouping | N/A by design (currently) | missing/different by design | No explicit parent node/group graph model yet. |
| Accessibility API parity (ARIA, keyboard nav parity) | N/A (currently) | partial/missing | |
| Devtools-style state inspector parity | N/A (currently) | missing | |
| Collaboration / multi-user awareness | Plugin: sync_plugin (Yrs + awareness) | different by design (done) | Implemented via plugin architecture, not RF-style built-in surface. |
FerrumFlow is not only targeting parity. Some capabilities are intentionally stronger or more explicit than typical React Flow usage patterns:
Command interop guarantees (execute / undo / to_ops consistency)
The Command pipeline is designed so local execution, undo/redo, and operation replay can be tested for equivalence (command_interop), reducing divergence bugs.
Plugin-first architecture across behavior and rendering
Core editor capabilities (selection, viewport, minimap, clipboard, context menu, alignment, collaboration) are modeled as plugins instead of hardcoded monolith behavior.
CRDT collaboration as a first-class extension path
sync_plugin integrates Yrs awareness + graph ops, giving a concrete multi-user architecture beyond single-user canvas editing.
Clear separation of graph model, interaction lifecycle, and rendering
Graph / Viewport / Interaction / PluginContext boundaries are explicit, making it easier to evolve editor features without coupling everything into UI callbacks.
Rust-native integration potential
FerrumFlow can align with native Rust systems (state machines, persistence, sync backends, tooling) without requiring a browser-first runtime assumption.
Contributions welcome: propose a matrix in an issue or open a PR that extends this section.
Foundation work that unlocks most other extensions:
Node / Port private in the next release after migration APIs settle.No active schedule; keep these in mind when designing APIs above.
Contributions are welcome!
Feel free to open issues or PRs for:
Apache2.0
621 commits
Rust
100.0%