Build a Custom ComfyUI Node
In this tutorial you’ll build a ComfyUI custom node from scratch — a simple text-processing node that converts input text to uppercase. Along the way you’ll learn the node API, registration system, and packaging conventions.
Step 1: What Are Custom Nodes?
ComfyUI’s power comes from its node-based architecture. Each node is a Python class that receives inputs, processes them, and passes outputs to the next node in the graph.
Custom nodes let you extend ComfyUI with your own logic — anything from text manipulation to image filters to API calls. They live in the custom_nodes/ directory and are loaded automatically on startup.
Why Build Custom Nodes?
- Add pre-processing or post-processing steps to your workflow
- Integrate external APIs or local tools
- Create reusable building blocks for complex pipelines
- Share functionality with the ComfyUI community
A real-world example is the ThumperPromptEnhance node, which uses a local Qwen3-4B model to rewrite short prompts into detailed image descriptions — replacing a 10+ minute Gemma 12B pipeline with a ~40-second alternative.
Step 2: Create the Node Directory
Each custom node lives in its own folder inside ComfyUI’s custom_nodes/ directory. Create a new folder for your node:
# Navigate to your ComfyUI installationcd ~/.local/share/tr-desktop/apps/comfyui/# Create the custom node directorymkdir -p custom_nodes/my_text_tools
The directory name becomes the node pack’s identifier. Use snake_case for consistency with the ComfyUI ecosystem.
Directory Structure
A minimal custom node needs just one file:
custom_nodes/my_text_tools/__init__.py # Node class + registration
Larger node packs may split logic across multiple files, but the entry point is always __init__.py.
Step 3: Write the Node Class
Open custom_nodes/my_text_tools/__init__.py in your editor and paste the following:
class TextToUppercase:"""Converts input text to uppercase."""@classmethoddef INPUT_TYPES(cls):return {"required": {"text": ("STRING", {"multiline": True,"default": "hello world"}),}}RETURN_TYPES = ("STRING",)RETURN_NAMES = ("upper_text",)FUNCTION = "to_upper"CATEGORY = "text"def to_upper(self, text):return (text.upper(),)# --- Registration (required) ---NODE_CLASS_MAPPINGS = {"TextToUppercase": TextToUppercase,}NODE_DISPLAY_NAME_MAPPINGS = {"TextToUppercase": "Text to Uppercase",}
Anatomy of a Node Class
- INPUT_TYPES — classmethod that declares what inputs the node accepts and their types
- RETURN_TYPES — tuple of output type strings (e.g. "STRING", "IMAGE", "INT")
- RETURN_NAMES — human-readable labels for each output
- FUNCTION — name of the method ComfyUI calls when executing the node
- CATEGORY — determines where the node appears in the Add Node menu
Registration Dictionaries
Every __init__.py must export two dictionaries:
- NODE_CLASS_MAPPINGS — maps unique node IDs to their Python classes
- NODE_DISPLAY_NAME_MAPPINGS — maps node IDs to display names shown in the UI
Step 4: Register and Test
ComfyUI discovers custom nodes at startup. To load your new node:
- If ComfyUI is running, stop it from the Thumper-Run dashboard
- Relaunch ComfyUI — click Launch on the ComfyUI card
- Once running, right-click the canvas and open Add Node → text
- You should see Text to Uppercase in the list. Click it to place a new node on the canvas — it appears as a rectangular block with a text input field and an upper_text output socket.
- Type some text in the input field, wire the output to another node (e.g. a "Show Text" node or a CLIP text encoder), and click Queue Prompt to run it
Debugging
If your node doesn’t appear:
- Check the ComfyUI console output for import errors
- Verify NODE_CLASS_MAPPINGS is defined at module level (not inside a function)
- Ensure the directory has an __init__.py file (not just a .py script)
- Confirm the file has no syntax errors: python -c "import my_text_tools"
Testing the Output
To verify your node works, connect it to a "Show Text" node (if installed) or check the execution API response. A quick test:
# Queue the workflow and check the output in the API responsecurl -s http://localhost:8188/history | python -m json.tool | head -20
Step 5: Package for Sharing
If you want to share your node pack with others, follow these conventions:
Recommended Structure
my_text_tools/__init__.py # Registration + importsnodes/text_upper.py # TextToUppercase classtext_reverse.py # TextReverse class (example)requirements.txt # Python dependencies (if any)README.md # Usage instructions
For node packs with external dependencies, include a requirements.txt. ComfyUI Manager and Thumper-Run will install these automatically.
Publishing
- Push your node pack to a public Git repository
- Submit to the ComfyUI Manager registry for community discovery
- Or include the node pack directly in a Thumper manifest’s custom_nodes section
Key Takeaways
- Custom nodes live in custom_nodes/<your_folder>/__init__.py
- NODE_CLASS_MAPPINGS is required — without it, ComfyUI won’t discover your node
- Restart ComfyUI to load new or modified nodes
- Change your input between runs to bypass ComfyUI’s execution cache
- Use unique node IDs with a descriptive prefix to avoid collisions
Next Steps
- Learn ComfyUI workflows in depth — ComfyUI on Thumper guide
- Start with images first — First Image tutorial
- Create an app manifest — App Manifest tutorial
- Contribute to the project — Contributing guide