ButtonNode
The ComfyUI node that's just a button — and that's the point
First, the honest version: this node is a lie, and the lie is the point. ButtonNode has no inputs, no outputs, and its Python half literally returns {}. When you drop it on the canvas you get an empty little box with a single button - "Open Modal" - that pops open a counter dialog. It doesn't touch the model, doesn't route anything, doesn't change your image. What it is, is a demo node from a template for building ComfyUI extensions with React, TypeScript, and Vite. If you loaded a workflow and found a missing ButtonNode, you can usually just delete it and move on. If you've ever wondered how the fancier UI extensions you use actually work, it's also a genuinely great thing to read.
What it's actually demonstrating
This pack (a fork of Comfy Org's official React Extension Template) is a teaching project, and ButtonNode is its star exhibit. The clever part is where the button comes from. Look at the Python class in __init__.py and you'll see a stub:
class ButtonNode:
def __init__(self): pass
@classmethod
def INPUT_TYPES(cls):
return {"required": {}, "optional": {}, "hidden": {}}
RETURN_TYPES = ()
CATEGORY = "ui"
OUTPUT_NODE = True
def process(self):
return {}
Nothing there creates a button widget. The button is injected by the JavaScript half. In ui/src/main.tsx, the extension calls comfy.registerExtension() and hooks beforeRegisterNodeDef, which grabs every ButtonNode as it's registered and patches onNodeCreated to call this.addWidget("button", "Open Modal", ...). So the widget you see is drawn client-side at the moment the node is created - ComfyUI's graph never knew about it. That's the whole trick of "frontend extensions": a WEB_DIRECTORY-style route (EXTENSION_WEB_DIRS, actually) serving a built JS bundle that ComfyUI loads on page startup, alongside a Python node that's mostly ceremony.
That's also why the node is marked OUTPUT_NODE with zero outputs - it's a terminal widget, not part of the data flow. Nothing wires into it and nothing comes out.
Installing it (this is the real gotcha)
This is not a ComfyUI Manager install-and-forget node, even though Manager will happily clone it. The README's flow is manual because there's a build step:
cd ComfyUI/custom_nodes
git clone https://github.com/vjumpkung/pixellatent-comfyui-frontend-react-extension-template
cd pixellatent-comfyui-frontend-react-extension-template/ui
npm install
npm run build
Then restart ComfyUI. You need Node.js 18+ - if you don't have a Node toolchain, that's the friction point. There are no Python dependencies and no model files to download; the only thing the backend needs is the compiled dist/ folder. Manager clones the repo but doesn't run npm run build, so the classic failure is: installed via Manager, restarted, and the extension doesn't load. Watch the ComfyUI console on startup - the pack prints a loud WARNING: dist directory not found if the build is missing.
Troubleshooting, in order of likelihood
- "dist directory not found" in the startup log - you skipped the build. Run
npm install && npm run buildinsideui/and restart ComfyUI. - ButtonNode is in the node menu but shows no button - the JS bundle didn't load or is stale. Rebuild and restart; the frontend won't pick up a new build without it.
- A toast says "Hello World!" on startup - that's not an error, it's the template announcing itself. Same with the "Counter" sidebar tab and top-bar menu it registers. It means the extension loaded fine.
- You only grabbed this for one workflow - consider uninstalling it when you're done. Custom nodes run arbitrary code in your Python environment, and the ComfyUI ecosystem has been burned by that (the LLMVISION malware incident is the canonical case). Keeping a demo extension you don't use is exactly the kind of clutter that bites later.
If you're here because you want to build a ComfyUI UI extension, this template is worth studying - the singleton dialog pattern, the typed stubs for /scripts/app.js, the Vite dev-server proxy, all of it is in ui/src/. For actually shipping something, the official Comfy-Org React Extension Template is the maintained baseline; this one is a personal variant. For anything else: delete the node, and consider the mystery solved.
Inputs (0)
No inputs
Outputs (0)
No outputs