nealepetrillo/claude-skills-retejs · Archived

retejs

This skill should be used when the user asks to "create a node editor", "build a visual workflow", "create a node-based interface", "add rete.js", "build a node graph", "create a dataflow editor", "build a visual programming interface", "connect nodes", or needs to implement visual node editors, workflow builders, or dataflow/control-flow processing using Rete.js v2 with Lit or vanilla JavaScript.

First seen Apr 27, 2026

Installation

$ npx skills add nealepetrillo/claude-skills-retejs --skill retejs

Summary

This skill should be used when the user asks to "create a node editor", "build a visual workflow", "create a node-based interface", "add rete.js", "build a node graph", "create a dataflow editor", "build a visual programming interface", "connect nodes", or needs to implement visual node editors, workflow builders, or dataflow/control-flow processing using Rete.js v2 with Lit or vanilla JavaScript.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version0.1.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 11,994 B
  • docs SUMMARY.md 414 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Rete.js v2 Visual Editor Skill

Create professional node-based editors and visual programming interfaces using Rete.js v2. Supports custom nodes, connections, dataflow/control-flow processing, and comprehensive E2E testing.

Version: Rete.js 2.x | Documentation: https://retejs.org/docs

Core Concepts

Framework-Agnostic Architecture

Rete.js is NOT bound to any UI framework. For lightweight implementations without React/Vue/Angular:

  • Use Lit (@retejs/lit-plugin) - Web Components based, minimal overhead
  • Use vanilla JS with manual DOM rendering for maximum control

Plugin System

Rete.js uses scope-based plugin architecture where signals propagate from parent to child:

import { Scope } from 'rete';

const parentScope = new Scope<number>('parent');
const childScope = new Scope<string, [number]>('child');

parentScope.addPipe((context) => {
  console.log('parent', context);
  return context;
});

parentScope.use(childScope);
await parentScope.emit(1);

Installation

NPM (Recommended for Lit)

npm i rete rete-area-plugin rete-connection-plugin @retejs/lit-plugin rete-render-utils

CDN (Vanilla JS)

<script src="https://cdn.jsdelivr.net/npm/rete/rete.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/rete-area-plugin/rete-area-plugin.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/rete-connection-plugin/rete-connection-plugin.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/rete-render-utils/rete-render-utils.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@retejs/lit-plugin/retejs-lit-plugin.min.js"></script>

CDN namespaces: Rete, ReteAreaPlugin, ReteConnectionPlugin, ReteLitPlugin

Core Pattern (Lit-based)

import { NodeEditor, GetSchemes, ClassicPreset } from "rete";
import { AreaPlugin, AreaExtensions } from "rete-area-plugin";
import { ConnectionPlugin, Presets as ConnectionPresets } from "rete-connection-plugin";
import { LitPlugin, Presets } from "@retejs/lit-plugin";

// Type definitions
type Schemes = GetSchemes<
  ClassicPreset.Node,
  ClassicPreset.Connection<ClassicPreset.Node, ClassicPreset.Node>
>;
type AreaExtra = LitArea2D<Schemes>;

// Initialize editor
const editor = new NodeEditor<Schemes>();
const area = new AreaPlugin<Schemes, AreaExtra>(container);
const connection = new ConnectionPlugin<Schemes, AreaExtra>();
const render = new LitPlugin<Schemes, AreaExtra>();

// Configure presets
render.addPreset(Presets.classic.setup());
connection.addPreset(ConnectionPresets.classic.setup());

// Connect plugins
editor.use(area);
area.use(connection);
area.use(render);

// Create socket
const socket = new ClassicPreset.Socket("socket");

// Create and add nodes
const nodeA = new ClassicPreset.Node("Node A");
nodeA.addOutput("out", new ClassicPreset.Output(socket, "Output"));
await editor.addNode(nodeA);

// Position nodes
await area.translate(nodeA.id, { x: 100, y: 100 });

// Fit viewport
AreaExtensions.zoomAt(area, editor.getNodes());

Custom Node Classes

Extend ClassicPreset.Node to create custom nodes. Define width and height for layout compatibility. Add inputs, outputs, and controls in the constructor. Implement a data() method for dataflow engine integration.

For type-safe connections, extend ClassicPreset.Socket with isCompatibleWith() to restrict which sockets can connect.

See references/editor-examples.md for complete examples including NumberNode, AddNode, custom socket types, dynamic inputs, and dropdown controls.

Processing Engines

Dataflow Engine (Data-Driven)

Processes graphs where data flows from outputs to inputs:

import { DataflowEngine } from "rete-engine";

const engine = new DataflowEngine<Schemes>();
editor.use(engine);

// Fetch result from a node
const result = await engine.fetch(resultNode.id);
console.log(result); // { value: 42 }

// Clear cache when inputs change
engine.reset();

Control Flow Engine (Execution-Driven)

Processes graphs where execution flows through explicit control connections:

import { ControlFlowEngine } from "rete-engine";

class StartNode extends ClassicPreset.Node {
  constructor() {
    super("Start");
    this.addOutput("exec", new ClassicPreset.Output(execSocket, "Execute"));
  }

  execute(_: never, forward: (output: "exec") => void) {
    forward("exec"); // Trigger next node
  }
}

class LogNode extends ClassicPreset.Node {
  constructor(message: string) {
    super("Log");
    this.addInput("exec", new ClassicPreset.Input(execSocket, "Execute"));
    this.addOutput("exec", new ClassicPreset.Output(execSocket, "Execute"));
    this.addControl("message", new ClassicPreset.InputControl("text", { initial: message }));
  }

  execute(_: "exec", forward: (output: "exec") => void) {
    const msg = (this.controls["message"] as ClassicPreset.InputControl<"text">).value;
    console.log(msg);
    forward("exec");
  }
}

const engine = new ControlFlowEngine<Schemes>();
editor.use(engine);

// Start execution
engine.execute(startNode.id);

Hybrid Engine (Combined)

For nodes that need both data and execution flow:

const dataflow = new DataflowEngine<Schemes>(({ inputs, outputs }) => ({
  inputs: () => Object.keys(inputs).filter(name => name !== "exec"),
  outputs: () => Object.keys(outputs).filter(name => name !== "exec")
}));

const controlflow = new ControlFlowEngine<Schemes>(() => ({
  inputs: () => ["exec"],
  outputs: () => ["exec"]
}));

editor.use(dataflow);
editor.use(controlflow);

Connection Validation

import { getConnectionSockets } from "rete-render-utils";

function canCreateConnection(editor: NodeEditor<Schemes>, connection: Schemes["Connection"]) {
  const { source, target } = getConnectionSockets(editor, connection);
  return source && target && source.isCompatibleWith(target);
}

editor.addPipe((context) => {
  if (context.type === "connectioncreate") {
    if (!canCreateConnection(editor, context.data)) {
      console.warn("Incompatible sockets");
      return; // Block connection
    }
  }
  return context;
});

Import/Export (Serialization)

Serialize graphs by iterating editor.getNodes() and editor.getConnections(), capturing node positions from area.nodeViews. Deserialize by clearing the editor, recreating nodes via a type-keyed factory, preserving original IDs, and restoring connections.

See references/editor-examples.md for complete export/import patterns with SerializedGraph interfaces.

Essential Plugins

Auto Arrange

npm i rete-auto-arrange-plugin elkjs web-worker
import { AutoArrangePlugin, Presets as ArrangePresets } from "rete-auto-arrange-plugin";

const arrange = new AutoArrangePlugin<Schemes>();
arrange.addPreset(ArrangePresets.classic.setup());
area.use(arrange);

await arrange.layout(); // Auto-arrange all nodes

Context Menu

npm i rete-context-menu-plugin
import { ContextMenuPlugin, Presets as ContextMenuPresets } from "rete-context-menu-plugin";

const contextMenu = new ContextMenuPlugin<Schemes>({
  items: ContextMenuPresets.classic.setup([
    ["Number", () => new NumberNode()],
    ["Add", () => new AddNode()],
    ["Math", [
      ["Multiply", () => new MultiplyNode()],
      ["Divide", () => new DivideNode()]
    ]]
  ])
});

area.use(contextMenu);
render.addPreset(Presets.contextMenu.setup());

History (Undo/Redo)

npm i rete-history-plugin
import { HistoryPlugin, HistoryActions, HistoryExtensions, Presets as HistoryPresets } from "rete-history-plugin";

const history = new HistoryPlugin<Schemes, HistoryActions<Schemes>>();
history.addPreset(HistoryPresets.classic.setup());
area.use(history);

// Enable keyboard shortcuts (Ctrl+Z, Ctrl+Y)
HistoryExtensions.keyboard(history);

// Programmatic undo/redo
await history.undo();
await history.redo();

Minimap

npm i rete-minimap-plugin
import { MinimapPlugin } from "rete-minimap-plugin";

const minimap = new MinimapPlugin<Schemes>();
area.use(minimap);
render.addPreset(Presets.minimap.setup({ size: 200 }));

Readonly Mode

npm i rete-readonly-plugin
import { ReadonlyPlugin } from "rete-readonly-plugin";

const readonly = new ReadonlyPlugin<Schemes>();
editor.use(readonly.root);
editor.use(area);
area.use(readonly.area);

// Enable/disable readonly
readonly.enable();  // Block user modifications
readonly.disable(); // Allow modifications

Selection System

Selectable Nodes

const selector = AreaExtensions.selector();
const accumulating = AreaExtensions.accumulateOnCtrl();

AreaExtensions.selectableNodes(area, selector, { accumulating });
AreaExtensions.simpleNodesOrder(area); // Bring selected to front

// Programmatic selection
selectableNodes.select(nodeId);        // Select single
selectableNodes.select(nodeId, true);  // Add to selection
selectableNodes.unselect(nodeId);      // Remove from selection

E2E Testing with Playwright

Test Rete.js editors using Playwright with data-testid attributes on nodes, sockets, and connections. Add test IDs via render.addPreset(Presets.classic.setup({ customize: { ... } })). Use the rete-qa package for regression testing across browsers.

See references/testing-guide.md for complete setup, test utilities, Page Object Models, and test suites covering node creation, connections, controls, serialization, and CI/CD integration.

Graph Operations (rete-structures)

npm i rete-structures
import { structures } from 'rete-structures';

const graph = structures(editor);

// Traversal
graph.roots();                 // Nodes without incoming connections
graph.leaves();                // Nodes without outgoing connections
graph.incomers(nodeId);        // Direct predecessors
graph.outgoers(nodeId);        // Direct successors
graph.predecessors(nodeId);    // All upstream nodes
graph.successors(nodeId);      // All downstream nodes

// Set operations
graph.filter(nodePredicate, connectionPredicate);
graph.union(otherGraph);
graph.difference(otherGraph);
graph.intersection(otherGraph);

Best Practices

Node Design

  1. Fixed dimensions - Define width and height on custom nodes for minimap/arrange
  2. Descriptive labels - Use clear node names that explain purpose
  3. Typed sockets - Use custom socket classes for type safety
  4. Control validation - Validate control input values

Performance

  1. Limit visible nodes - Use virtualization for large graphs
  2. Debounce processing - Don't recompute on every change
  3. Cache engine results - Call engine.reset() only when necessary

Testing

  1. Add data-testid attributes - Enable reliable E2E selectors
  2. Test serialization - Verify import/export roundtrips
  3. Test edge cases - Cycles, disconnected nodes, invalid connections

Additional Resources

Reference Files

For detailed patterns and complete code examples, consult:

  • references/editor-examples.md - Complete node implementations, custom sockets, serialization, plugin setup, and graph utilities
  • references/testing-guide.md - Playwright setup, Page Object Models, test suites, visual regression, and CI/CD integration

External Documentation