fbp-graph-editor

Houdini-inspired graph editor for Flow-Based Programming built with React. Use when building or customizing a visual graph editor, working with the @fbp/graph-editor package.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "fbp-graph-editor" with this command: npx skills add constructive-io/constructive-skills/constructive-io-constructive-skills-fbp-graph-editor

Houdini-inspired graph editor for Flow-Based Programming built with React.

Installation

pnpm add @fbp/graph-editor

Overview

@fbp/graph-editor is a React component for visual editing of FBP graphs. It features an SVG-based canvas with pan/zoom, node rendering with fully-qualified type paths, Bezier edge connections, selection system, properties panel, and subgraph navigation.

Basic Usage

import { GraphEditor } from '@fbp/graph-editor';
import type { Graph, NodeDefinition } from '@fbp/types';

const graph: Graph = {
  name: 'my-graph',
  definitions: [
    {
      context: 'js',
      category: 'math',
      type: 'js/math/add',
      inputs: [
        { name: 'a', type: 'number' },
        { name: 'b', type: 'number' }
      ],
      outputs: [
        { name: 'sum', type: 'number' }
      ]
    }
  ],
  nodes: [
    { name: 'add1', type: 'js/math/add', meta: { x: 100, y: 100 } }
  ],
  edges: []
};

function App() {
  return (
    <div className="h-screen">
      <GraphEditor graph={graph} />
    </div>
  );
}

Features

SVG-Based Canvas

The editor uses SVG for rendering, providing crisp visuals at any zoom level. Pan and zoom are supported via mouse/trackpad gestures.

Node Rendering

Nodes display their fully-qualified type paths (e.g., js/math/add) and show input/output ports based on their definition.

Bezier Edge Connections

Edges are rendered as smooth Bezier curves connecting output ports to input ports. Click and drag from a port to create new connections.

Selection System

  • Click to select a single node
  • Shift+click to add/remove from selection
  • Box select with Shift+drag
  • Cmd/Ctrl+A to select all
  • Escape to clear selection
  • Cmd/Ctrl+D to duplicate selection

Properties Panel

Auto-generated from PropDefinition. When a node is selected, its properties are displayed in a panel for editing.

Subgraph Navigation

  • Enter to dive into a selected subnet
  • U to go up from a subnet

Keyboard Shortcuts

ShortcutAction
Delete/BackspaceDelete selected nodes/edges
Cmd/Ctrl+DDuplicate selection
Cmd/Ctrl+ASelect all
EscapeClear selection
EnterDive into selected subnet
UGo up from subnet
Shift+DragBox select
Alt+Drag or Middle MousePan canvas
Ctrl/Cmd+ScrollZoom

Channel Reference Detection

The editor detects channel references in property values using patterns like ch("...") and $VAR, enabling visual feedback for connected parameters.

Styling

The editor uses Tailwind CSS for styling. Ensure your project has Tailwind configured:

// tailwind.config.js
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
    './node_modules/@fbp/graph-editor/**/*.{js,ts,jsx,tsx}'
  ],
  // ...
};

Props

interface GraphEditorProps {
  graph: Graph;
  onChange?: (graph: Graph) => void;
  definitions?: NodeDefinition[];
  readOnly?: boolean;
}
PropTypeDescription
graphGraphThe graph to display and edit
onChange(graph: Graph) => voidCallback when graph changes
definitionsNodeDefinition[]Additional node type definitions
readOnlybooleanDisable editing

Peer Dependencies

{
  "peerDependencies": {
    "react": ">=18.0.0",
    "react-dom": ">=18.0.0"
  }
}

Example: Complete Editor Setup

import { useState } from 'react';
import { GraphEditor } from '@fbp/graph-editor';
import type { Graph } from '@fbp/types';

const initialGraph: Graph = {
  name: 'calculator',
  definitions: [
    {
      type: 'js/const/number',
      context: 'js',
      category: 'const',
      props: [{ name: 'value', type: 'number', default: 0 }],
      outputs: [{ name: 'value', type: 'number' }]
    },
    {
      type: 'js/math/add',
      context: 'js',
      category: 'math',
      inputs: [
        { name: 'a', type: 'number' },
        { name: 'b', type: 'number' }
      ],
      outputs: [{ name: 'sum', type: 'number' }]
    }
  ],
  nodes: [
    { name: 'num1', type: 'js/const/number', meta: { x: 50, y: 50 }, props: [{ name: 'value', value: 5 }] },
    { name: 'num2', type: 'js/const/number', meta: { x: 50, y: 150 }, props: [{ name: 'value', value: 3 }] },
    { name: 'add', type: 'js/math/add', meta: { x: 250, y: 100 } }
  ],
  edges: [
    { src: { node: 'num1', port: 'value' }, dst: { node: 'add', port: 'a' } },
    { src: { node: 'num2', port: 'value' }, dst: { node: 'add', port: 'b' } }
  ]
};

function App() {
  const [graph, setGraph] = useState(initialGraph);

  return (
    <div className="h-screen flex flex-col">
      <header className="p-4 border-b">
        <h1 className="text-xl font-bold">{graph.name}</h1>
      </header>
      <main className="flex-1">
        <GraphEditor 
          graph={graph} 
          onChange={setGraph}
        />
      </main>
    </div>
  );
}

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

constructive-graphql-codegen

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

github-workflows-ollama

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

github-workflows-pgpm

No summary provided by upstream source.

Repository SourceNeeds Review