Rete.js: Visual Programming Framework

2.0.6 · active · verified Sun Apr 19

Rete.js is a robust JavaScript framework for building visual programming interfaces and workflows, allowing developers to create node-based editors for dataflow, control flow, or mixed processing. It provides out-of-the-box solutions for visualization with various UI libraries (React, Vue, Angular, Svelte, Lit) and offers different types of engines for graph processing. The current stable version is 2.0.6, with recent minor updates addressing bug fixes and performance improvements. Rete.js v2 represents a significant architectural shift from v1, adopting a TypeScript-first approach, a flexible plugin system, and enhanced customization capabilities. Its modular ecosystem allows developers to pick and choose necessary packages, avoiding unnecessary dependencies and supporting custom builds.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to set up a basic Rete.js editor with a custom node, two instances of that node, and a connection between them using the React renderer. It highlights the use of `NodeEditor`, `AreaPlugin`, `ConnectionPlugin`, and `ReactPlugin` with `ClassicPreset` for defining schemes and components.

import { NodeEditor, GetSchemes, ClassicPreset } from 'rete';
import { AreaPlugin, AreaExtensions } from 'rete-area-plugin';
import { ConnectionPlugin } from 'rete-connection-plugin';
import { ReactPlugin, Presets, ReactArea2D } from 'rete-react-plugin';
import { createRoot } from 'react-dom/client';

type Schemes = GetSchemes<
  ClassicPreset.Node,
  ClassicPreset.Connection<ClassicPreset.Node, ClassicPreset.Node>
>;
type AreaExtra = ReactArea2D<Schemes>;

const socket = new ClassicPreset.Socket('Number');

class MyNode extends ClassicPreset.Node {
  width = 180;
  height = 120;
  constructor(name: string, numValue: number = 0) {
    super(name);
    this.addControl('value', new ClassicPreset.InputControl('number', { initialValue: numValue }));
    this.addOutput('num', new ClassicPreset.Output(socket, 'Number'));
  }
}

async function createEditor(container: HTMLElement) {
  const editor = new NodeEditor<Schemes>();
  const area = new AreaPlugin<Schemes, AreaExtra>(container);
  const connection = new ConnectionPlugin<Schemes, AreaExtra>();
  const render = new ReactPlugin<Schemes, AreaExtra>();

  AreaExtensions.zoomAt(area, editor.getNodes());
  AreaExtensions.simpleNodesOrder(area);

  render.addPreset(Presets.contextMenu.setup());
  render.addPreset(Presets.classic.setup());

  editor.use(area);
  area.use(connection);
  area.use(render);

  const nodeA = new MyNode('A', 10);
  const nodeB = new MyNode('B', 20);

  await editor.addNode(nodeA);
  await editor.addNode(nodeB);
  await area.translate(nodeA.id, { x: 0, y: 0 });
  await area.translate(nodeB.id, { x: 250, y: 0 });

  const connectionAtoB = new ClassicPreset.Connection(nodeA, 'num', nodeB, 'num');
  await editor.addConnection(connectionAtoB);

  // Render the editor
  const root = createRoot(container);
  root.render(<ReactArea2D area={area} 
    // Pass extra props if needed
  />);

  console.log('Rete.js editor initialized with two nodes and a connection.');
  return editor;
}

// To run this in a browser:
// const container = document.getElementById('rete-container');
// if (container) { createEditor(container); }

view raw JSON →