Skip to main content

streamlit-node-editor-v2

A Streamlit Custom Component v2 for building ComfyUI- and Unreal Blueprints-style node graphs. Users can add nodes, edit parameters, connect typed ports, move and select nodes, select and delete connections, pan and zoom the canvas, and serialize the graph back to Python.

Installation

uv pip install streamlit-node-editor-v2

The package includes the compiled frontend assets. The public Python entry point is st_node_editor:

import streamlit as st
from streamlit_node_editor_v2 import st_node_editor

st.title("Pipeline editor")

graph = st_node_editor(key="pipeline")
if graph:
      st.json(graph)

Component API

st_node_editor(
      name="Node Editor",
      node_defs=None,
      height=700,
      background_color="#080810",
      show_border=True,
      initial_nodes=None,
      initial_connections=None,
      key=None,
      on_node_selected_change=None,
      on_connection_selected_change=None,
      on_connection_added_change=None,
      on_connection_deleted_change=None,
)

Arguments

Argument Description
name Name passed to the component. Defaults to "Node Editor".
node_defs Dictionary defining the available node types. When omitted or empty, the built-in definitions are used.
height Component height in pixels. Defaults to 700.
background_color CSS color for the canvas. Defaults to "#080810".
show_border Whether to draw a border around the canvas.
initial_nodes Nodes placed when the component first loads.
initial_connections Connections restored when the component first loads.
key Stable Streamlit key. Required when reading event payloads from st.session_state.
on_*_change Optional no-argument callbacks for component events.

The function returns a dict-like component result with nodes and connections. It is empty or unavailable before the first frontend update.

Node definition JSON

node_defs is a mapping from the displayed node type name to its definition. The following is a complete example:

{
   "Load Data": {
      "category": "Sources",
      "headerColor": "#4ade80",
      "inputs": [],
      "outputs": [
         {"name": "data", "type": "DATAFRAME"}
      ],
      "params": [
         {
            "key": "path",
            "label": "CSV path",
            "type": "string",
            "default": "data/input.csv"
         }
      ]
   },
   "Filter Rows": {
      "category": "Transforms",
      "headerColor": "#38bdf8",
      "inputs": [
         {"name": "data", "type": "DATAFRAME"}
      ],
      "outputs": [
         {"name": "data", "type": "DATAFRAME"}
      ],
      "params": [
         {
            "key": "query",
            "label": "Query",
            "type": "textarea",
            "default": "value > 0"
         }
      ]
   },
   "Choose Model": {
      "category": "Configuration",
      "headerColor": "#c084fc",
      "inputs": [],
      "outputs": [
         {"name": "model", "type": "MODEL"}
      ],
      "params": [
         {
            "key": "model",
            "label": "Model",
            "type": "select",
            "options": ["small", "medium", "large"]
         }
      ]
   }
}

Node definition fields

  • category: Palette grouping label.
  • headerColor: CSS color for the node header.
  • inputs: List of input ports.
  • outputs: List of output ports.
  • params: List of inline editable parameters.
  • x and y: Optional initial position for built-in or supplied definitions.

Each port has a name and type. Input ports may also set maxConnections; the default is 1. Port types connect when their type names match, or when either side is ANY.

Each parameter has a key, label, and one of these types:

  • string: Single-line text input.
  • textarea: Multiline text input.
  • int: Integer input with step controls.
  • float: Decimal input with step controls.
  • select: Select box; options is required. If default is omitted, the first option is used and returned in the graph state.

Initial graph JSON

Nodes can be supplied using initial_nodes:

[
   {
      "id": "load-1",
      "type": "Load Data",
      "x": 80,
      "y": 120,
      "params": {
         "path": "data/input.csv"
      }
   },
   {
      "id": "filter-1",
      "type": "Filter Rows",
      "x": 420,
      "y": 120,
      "params": {
         "query": "value > 0"
      }
   }
]

Connections can be supplied using initial_connections:

[
   {
      "id": "wire-1",
      "fromNode": "load-1",
      "fromPort": 0,
      "toNode": "filter-1",
      "toPort": 0
   }
]

Port indexes are zero-based. The referenced node IDs and port indexes must exist.

Returned graph state

The component result has this shape:

{
      "nodes": [
            {
                  "id": "load-1",
                  "type": "Load Data",
                  "x": 80,
                  "y": 120,
                  "params": {"path": "data/input.csv"},
            },
      ],
      "connections": [
            {
                  "id": "wire-1",
                  "fromNode": "load-1",
                  "fromPort": 0,
                  "toNode": "filter-1",
                  "toPort": 0,
            },
      ],
}

User interactions

  • ADD NODE opens the node palette. Nodes can also be added from the canvas context menu.
  • Drag a node to reposition it.
  • Click a node to select it. DELETE NODE removes selected nodes and their connections.
  • Drag between compatible ports to create a connection.
  • Click a connection to select it. The connection is highlighted, and DELETE CONNECTION becomes available.
  • AUTO-CONNECT creates compatible connections while avoiding cycles and connection limits.
  • AUTO-DISCONNECT removes all connections but keeps the nodes.
  • RESET restores pan and zoom.
  • Mouse wheel zooms the canvas. Middle-button dragging pans it; right-click opens the canvas context menu.
  • Delete or Backspace removes selected nodes.

Event callbacks

Callbacks are no-argument functions. The event payload is available during the callback in the component's Streamlit session state. The callback names and payload keys are:

Callback Payload
on_node_selected_change Selected node under st.session_state[key].node_selected
on_connection_selected_change Selected connection under st.session_state[key].connection_selected
on_connection_added_change New connection under st.session_state[key].connection_added
on_connection_deleted_change Deleted connection under st.session_state[key].connection_deleted

Example:

import streamlit as st
from streamlit_node_editor_v2 import st_node_editor

COMPONENT_KEY = "pipeline"


def selected_node():
      st.session_state["last_event"] = {
            "name": "node_selected",
            "value": st.session_state[COMPONENT_KEY].node_selected,
      }


def connection_added():
      st.session_state["last_event"] = {
            "name": "connection_added",
            "value": st.session_state[COMPONENT_KEY].connection_added,
      }


graph = st_node_editor(
      key=COMPONENT_KEY,
      on_node_selected_change=selected_node,
      on_connection_added_change=connection_added,
)

if "last_event" in st.session_state:
      st.json(st.session_state["last_event"])

The same pattern applies to on_connection_selected_change and on_connection_deleted_change. Events are triggers for the current rerun; the persistent graph is read from the component result.

Development setup

Requirements:

  • Python 3.10 or newer.
  • Node.js 24 or newer.
  • uv for Python environment and package management.

Install frontend dependencies:

cd streamlit_node_editor_v2/frontend
npm install

Build and typecheck the frontend:

npm run typecheck
npm run build

npm run build cleans the frontend build directory, typechecks TypeScript, and writes one hashed index-*.js bundle to frontend/build.

Install the repository in editable mode from the project root:

uv pip install -e . --force-reinstall

Run the example app:

streamlit run example.py

When frontend source changes, rebuild the frontend and restart or refresh the Streamlit app so it serves the new hashed bundle.

Packaging

Build the frontend first:

cd streamlit_node_editor_v2/frontend
npm run build
cd ../..

Build the Python distributions from the project root:

uv build

The resulting dist/ directory contains the wheel and source distribution. The wheel includes streamlit_node_editor_v2/frontend/build and the package manifest that registers the v2 component asset directory.

Install and test the wheel locally:

uv pip install dist/streamlit_node_editor_v2-*.whl --force-reinstall
streamlit run example.py

Do not remove the [[tool.streamlit.component.components]] entry from the root pyproject.toml; Streamlit uses it to resolve the packaged index-*.js asset.

Metadata

Release files for streamlit-node-editor-v2 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for streamlit-node-editor-v2 0.0.1
File Size Uploaded Provenance
streamlit_node_editor_v2-0.0.1.tar.gz 61.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for streamlit-node-editor-v2 0.0.1
File Interpreter ABI Platform
streamlit_node_editor_v2-0.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 121.2 kB

Release files / streamlit_node_editor_v2-0.0.1.tar.gz

Download URL streamlit_node_editor_v2-0.0.1.tar.gz
Size 61.8 kB
Tags Source
SHA-256 checksum
How to use checksums
319abc0a89c2d5e8ed05ea2357da00ed9e7fbb58a38573848eee3cf6fadedced
BLAKE2b-256 checksum
How to use checksums
6591736a889822e583fb8f3c463fd1c35adef27149050768d82580de6b0eb733
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / streamlit_node_editor_v2-0.0.1-py3-none-any.whl

Download URL streamlit_node_editor_v2-0.0.1-py3-none-any.whl
Size 59.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81f9bb4ac44069df306ae85ee0d9420a307c45b1e2829e02a4d373b9a9136391
BLAKE2b-256 checksum
How to use checksums
08940e0f2c599f52873e6777515e5cd4d89efa5f2a63d3172dff7f17e0856b30
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Security for streamlit-node-editor-v2 0.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page