ui_1_starting - chrisgoringe/Comfy-Custom-Node-How-To GitHub Wiki

First steps in extending the UI

Making your node send a message

class MyNode:
  IS_OUTPUT = True
...
  def the_func(self, input, ...):

    return { "ui": {"name":value}, "result" : (the output tuple) }

Only output nodes send a message back to the front end; the message is defined by replacing the usual tuple at the end of your function with a dictionary where the tuple is keyed to result and a message dictionary is keyed to ui.

How to register an extension

You'll most likely want to write something like:

import { app } from "../../../scripts/app.js";
app.registerExtension({                                                                       // 1
	name: "a.unqiue.name.for.this.extension",
	async beforeRegisterNodeDef(nodeType, nodeData, app) {                                // 2
		if (node?.comfyClass === "The unique name of my node class on the backend") { // 3
			const onExecuted = nodeType.prototype.onExecuted;                     // 4
			nodeType.prototype.onExecuted = function (message) {
				onExecuted?.apply(this, arguments);                           // 5
				// do something with the message                              // 6
			}
		}
	},
}),

Walking through that:

  • 1 Using the ComfyUI app.js we're registering an extension by passing a unique name and an async function
  • 2 The function name determines when it is called - see below
  • 3 beforeRegisterNodeDef is called for every nodeType so check if it's your node
  • 4 onExecuted is called when the node finishes executing. If there's already an onExecuted method, save it in the const
  • 5 replace onExecuted with your new code; the first line of which calls the one you saved
  • 5a the only other useful method to replace is onExecutionStart, which is called without parameters at the start of a run
  • 6 message is that dictionary you defined in the python 'ui' return

What method names?

Search in app.js for invokeExtensions - these are the methods that can be used at 2 to get your code called during the startup process.

Method Parameters Called Returns
init None When the page is loaded, before any nodes or workflow
setup None At the end of the setup
addCustomNodeDefs defs - the node_info for each type of node Once before any node types are defined
getCustomWidgets None Once to generate a list of custom widgets Custom Widget
nodeCreated The ComfyNode object for a node type Once for each node type as created
beforeRegisterNodeDef The ComfyNode object for a node type, and it's node_data Once for each node type after created, before registering with LiteGraph
registerCustomNodes None Once after all custom node types have been added
loadedGraphNode node for each node when it is loaded not called async

How to deploy JavaScript

Add a js folder to your repository, and in __init__.py include code along these lines:

WEB_DIRECTORY = "./js"
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]

When ComfyUI loads your custom node, the js directory will be copied to [comfy]/web/extensions/A_UNIQUE_NAME, and all .js files in it will be sent to the browser and executed when the page is loaded.