Text Prompt Builder
Templates beat copy-paste for assembling ComfyUI prompts
- string
This is the node the pack is named for, and the one you'll actually reach for. Text Prompt Builder is a fill-in-the-blanks engine for prompts: you keep the pieces in Text Prompt Nodes, then this node stitches them into one final string using a template. Same idea as the block structure people keep evangelizing for modern models - quality tags in one block, scene in another, style in a third - except here the blocks are literal nodes you can swap without rewriting anything.
How it works
Two moving parts. The template input is a multiline string (defaults to {subject}, {style}) that defines the shape of the output. Then there are the dynamic variable_1, variable_2, … inputs, which are the clever bit: they don't exist until you need them. Connect something to variable_1 and a variable_2 slot materializes; disconnect it and trailing empty slots tidy themselves away. A little JS extension in the pack handles that, and it genuinely feels like magic the first time.
When the graph runs, the node collects everything connected, builds a lookup table, and feeds your template through Python's str.format(). You can reference a variable three ways:
- By name:
{subject}- matches thevar_nameyou set on the Text Prompt Node. - By slot:
{variable_1},{variable_2}. - By short suffix:
{1},{2}- handy when a connected input isn't a named Text Prompt Node.
The output is a plain string you wire into CLIP Text Encode (positive, negative, or both) or anywhere else that eats a STRING.
The inputs that matter
Honestly just template. The dynamic inputs are self-managing - you connect Text Prompt Nodes (or any string) and new slots appear. Unconnected slots become empty strings, so a template referencing a slot nobody filled just renders with a hole in it.
Where people get burned
Python's str.format() is the engine, which brings two traps. First, literal braces break it: if your template contains a { or } that isn't a placeholder - say you're writing a character description with curly quotes, or you copy a JSON snippet into a template - format() chokes. The pack handles this gracefully-ish: instead of crashing, it returns a string that literally reads Error: Missing variable {x} in template. Available variables: .... That's a debugging gift, but it's also a trap, because your prompt becomes an error message and it still renders. Watch for it.
Second, names with spaces or special characters don't work by name. {my subject} isn't a valid Python format key, so reference it as {1} by slot instead. Same fix if two variables share a var_name and you're not sure which is which.
One more distinction worth getting straight: this is not ComfyUI's {a|b|c} wildcard system. The pack explicitly disables dynamic prompts on its fields so your {subject} placeholders don't get eaten by the wildcard parser. If you want random variation, that's the other, orthogonal feature - and it still works on the output side if you want it to.
Installing it
Part of ComfyUI Prompt Builder - one install, all five nodes. ComfyUI Manager: search "ComfyUI Prompt Builder". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/aimoviestudio/comfyui-promptbuilder
Restart ComfyUI. No dependencies, no model downloads, nothing to babysit - the whole pack is pure Python plus that one JS file, and its requirements file is empty.
The honest take: it's a small node doing one small job, and for short prompts it's arguably overkill - you can type a one-liner faster than you can build a graph. Where it earns its keep is when you're iterating on a 60-word structured prompt and want to swap the style block without retyping everything, or when you're sharing workflows and want the prompt to read like a template instead of a wall of text.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| template | STRING | {subject}, {style} | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| string | STRING | — |