Defer removal of the 32 default Python outputs from onNodeCreated using queueMicrotask so they remain available during graph loading. ComfyUI creates all nodes before configuring them, and nodes like Kijai's SetNode resolve links during their configure step — if outputs were already removed, the resolution failed with "node input undefined". The deferred cleanup only runs for new nodes; loaded workflows set _configured=true in onConfigure first. Also adds a fallback to sync widget values from serialized outputs when widget restoration fails. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A collection of ComfyUI utility nodes: a dynamic JSON loader that auto-creates outputs from any JSON file, string/path helpers, and a preview-to-LoadImage bridge that lets you push generated images (with optional masks) into LoadImage nodes.
Features
- Auto-discovery — reads JSON keys and exposes them as named outputs
- Type detection —
INT,FLOAT,STRINGtypes with colored connectors - Batch support —
sequence_numberinput forbatch_dataarrays - Connection-safe refresh — adding new keys preserves existing links
- Workflow persistence — keys, types, and connections survive save/reload
Installation
ComfyUI Manager
Search for JSON Dynamic Loader in the ComfyUI Manager registry.
Manual
cd ComfyUI/custom_nodes/
git clone https://github.com/ethanfel/ComfyUI-JSON-Dynamic.git
# Restart ComfyUI
Usage
- Add JSON Dynamic Loader node to your workflow
- Enter a
json_pathandsequence_number - Click Refresh Outputs
- Outputs appear named after your JSON keys with correct types
- Connect to downstream nodes
Type Handling
| JSON type | Output type | Connector |
|---|---|---|
42 (integer) |
INT |
Blue |
3.14 (float) |
FLOAT |
Teal |
"hello" (string) |
STRING |
Pink |
true / false |
STRING ("true" / "false") |
Pink |
JSON Format
Flat JSON (single segment)
For simple use cases, the node reads keys directly from the root object. The sequence_number input is ignored.
{
"general_prompt": "A cinematic scene...",
"seed": 42,
"flf": 0.5,
"camera": "pan_left"
}
Batch JSON (multiple segments)
For multi-shot workflows, wrap entries in a batch_data array. Each entry is a segment representing one shot/scene with its own settings. The sequence_number input selects which segment to read.
{
"batch_data": [
{
"sequence_number": 1,
"general_prompt": "Wide establishing shot of a city",
"seed": 42,
"camera": "static",
"flf": 0.0
},
{
"sequence_number": 2,
"general_prompt": "Close-up of the protagonist",
"seed": 108,
"camera": "pan_left",
"flf": 0.5,
"my_custom_key": "only on this segment"
},
{
"sequence_number": 3,
"general_prompt": "Aerial drone shot over rooftops",
"seed": 77,
"camera": "zoom_in",
"flf": 0.8
}
]
}
Segment lookup
The node resolves which segment to read using this logic:
- Match by
sequence_numberfield — scansbatch_datafor an entry whosesequence_numbermatches the input - Fallback to array index — if no match is found, uses
sequence_number - 1as the array index (clamped to bounds) - No
batch_data— reads keys from the root object directly
This means segments don't need to be in order and can have gaps (e.g. 1, 5, 10). Each segment can have different keys — click Refresh Outputs after changing sequence_number if the keys differ between segments.
String & Path Utility Nodes
Four additional nodes that replace common multi-node chains for string and path operations.
Path Join (utils/path)
Joins 1–6 path segments using os.path.join with automatic normalization.
| Input | Type | Notes |
|---|---|---|
segment_1 |
STRING | Required |
segment_2 – segment_6 |
STRING | Optional |
Output: path (STRING)
String Format (utils/string)
Python format-string templating ({0}/{1:04d}.{2}) with up to 8 connected inputs. Handles zero-padding, type conversion, and arbitrary templates in one node.
| Input | Type | Notes |
|---|---|---|
template |
STRING | Format string, e.g. {0}/{1:04d} |
v0 – v7 |
any | Optional values to substitute |
Output: string (STRING)
String Extract (utils/string)
Extracts substrings with 3 modes:
| Mode | Description |
|---|---|
split_take |
Split on delimiter, take part at index (negative indices supported) |
between |
Extract text between two delimiters |
filename_parts |
Decompose path into dirname / basename / extension |
Outputs: result, dirname, basename, extension (all STRING)
String Switch (utils/string)
Boolean-based selection with built-in default values.
| Input | Type | Notes |
|---|---|---|
condition |
BOOLEAN | Required |
on_true / on_false |
any | Optional connected values |
default_true / default_false |
STRING | Fallback widget values |
Output: result (any)
When a connected input (on_true/on_false) is present it takes priority; otherwise the corresponding default_* string widget is used.
Image Utility Nodes
Preview to Load Image (utils/image)
Previews an image like the built-in PreviewImage node, but also saves a copy to ComfyUI's input/ folder so you can push it into any LoadImage node with one click.
| Input | Type | Notes |
|---|---|---|
images |
IMAGE | Required |
filename |
STRING | Name for the saved file (without extension, default preview) |
mask |
MASK | Optional — embedded as the PNG alpha channel |
Widgets (JS-side):
| Widget | Description |
|---|---|
load_image_node_id |
ID of the target LoadImage node |
| Send to Load Image | Button — sets the target node's image selector to the saved file |
How it works:
- On execution, the node saves a temp preview (displayed in the node) and a permanent copy to
input/{filename}.png - If a mask is connected, it is embedded as the PNG's alpha channel — LoadImage will automatically output it as its mask
- Enter the target LoadImage node's ID and click Send to Load Image — the target's image dropdown updates immediately, no restart needed