Prompt Template
Prompt templating with [bracket] variables — the node this pack is quietly built around
- tmpl_dict
- data
- STRING
Half of Chaser's Custom Nodes exists to feed this one. Prompt Template takes a Jinja template, renders it against a data dict, and hands you the resulting STRING to wire into a CLIP text encode or any other text input. If you've ever wanted to assemble prompts from structured data instead of hardcoding them, this is the payoff node.
The three inputs are template (multiline), an optional data dict (PYDICT), and an optional tmpl_dict (named templates). The output is the rendered string.
The first thing to learn: it uses [brackets], not {{ curly braces }}. The author reconfigured Jinja's variable delimiters to [ and ], so [subject] renders data["subject"]. This trips up everyone who copies in a normal Jinja template - {{ subject }} renders literally, brackets or nothing. Inside the template you still get full Jinja - loops, conditionals, filters - just with the bracket syntax for variables:
[subject], [style], masterpiece, best quality
{% if character %}character: [character]{% endif %}
How the data gets there. You can build the dict with YAML Data (readable config blocks), Set Data (single values), or Merge Data (layered defaults and overrides). The tmpl_dict input is where the pack's template registry plugs in: when you pass one, the environment switches to a DictLoader, so your template can {% include 'shared_negative' %} or {% import 'common' as common %} - which is how you pull in the macros from the shipped common.j2 and reuse prompt building blocks across the graph.
Why you'd go through this much trouble. Two reasons. First, reuse: one template drives many runs, with only the data dict changing. Second, structure: if you're prompting tag-based models (Illustrious and friends, per the current prompting wisdom), keeping your quality prefix, subject block, and negatives as named, versionable pieces beats rebuilding them by hand in every workflow. Change a negative in one registered template, every workflow that includes it updates.
Gotchas that will cost you an hour:
- Wrong delimiters.
[and]are the law here.{{ }}will silently render as text. - The
datadict keys must match the bracket names exactly.[subject]needsdata["subject"], not"Subject". - It's a string renderer, not an LLM. Values get stringified; a boolean
Falsein YAML becomes the textFalse. - No model involved, so a "templating bug" looks identical to a prompt problem - check the rendered string (feed it to a text preview node) before blaming the sampler.
Install is the pack standard - ComfyUI Manager, search "Chaser's Custom Nodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/chaserhkj/ComfyUI-Chaser-nodes
then restart. No model downloads; jinja2 (which does the actual templating), pyyaml, requests, sexpdata, and av install automatically. The README warns these are personal ad-hoc nodes "not meant to be used out of any context that I am already using them in" - for templating, the risk is mostly in the bracket syntax being nonstandard, so keep that in mind when borrowing someone else's template.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| template | STRING | — | |
| tmpl_dictopt | TMPL_DICT | — | |
| dataopt | PYDICT | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |