Prompt Template (MRLN)
The node that turns prompt retyping into a library
- prompt
- llm
- loras
- negative
- choices
- gen_info
The good prompt you wrote last month lives in a text file, a screenshot, or a workflow you have to open to read. When you want it again with a different car and a different season, you edit it by hand - and the edit is where the quality goes. That's the problem this pack was built around, and Prompt Template (MRLN) is the flagship: a node that composes a whole prompt from a curated JSON library instead of making you type it. It ships with 100 templates, 237 sections and 3502 items, every one carrying a thumbnail, so it's useful on the first render - not after an evening of authoring.
The pitch is reproducibility. Every slot in a template is fixed, random, or random-from-a-subset you ticked, and one seed decides every random slot. Same seed, same library files, same prompt, forever. A batch of eight is eight different draws rather than eight copies of one. That's the thing wildcards can't give you: a wildcard randomizes words but doesn't know what the words are for, can't weight one option over another, and can't be reproduced from a seed.
How it works
The library is plain JSON in two tiers. Factory content ships with the pack; your personal files live in ComfyUI/user/mrln/prompt/ and survive pack updates. A template is a set of slots, each naming a section - and the node resolves every slot, substitutes {variables} and inline {a|b} wildcards, joins the item texts with the section and item negatives, and renders in the template's format.
The profile dropdown is the genuinely 2026 feature. It reshapes the same library for a target model family - tag flow for the SDXL lineage, prose for the FLUX/KREA-class models whose encoders read instructions - and can reorder rendered blocks into the reading order that family rewards. If you've absorbed the encoder-shift reality, this is that knowledge baked into a widget.
The inputs that matter
template- the library template.triggerfills the{trigger}variable, usually your LoRA trigger word.seed- connect the same seed source as your sampler for lockstep.selection- per-slot overrides, oneslot=itemper line:slot=random,slot=random@123(its own seed),slot=offto mute.batch_count- see below.
Everything else - format, text_length, conflict_policy, selection_mode, profile - has sane defaults. Leave them alone until you need them.
The outputs, in wiring order
prompt goes to your CLIP encode, negative to the negative encode. Then the two wires that make this pack cohere: llm feeds Prompt Enhance, and loras feeds LoRA Apply. choices reports exactly what each slot drew (wire it into Show Text to read it), and gen_info is an A1111-style parameters string for a metadata-capable save node.
Batch is where this shines. batch_count > 1 makes every output a list, with item i drawn on master seed + i - so a "batch size 4" run gives four different images instead of the four identical copies that are ComfyUI's classic complaint. batch_mode "combinatorial" instead enumerates every combination of the still-random slots, capped at 512.
The gen_info output deliberately carries no Steps, Sampler, CFG or Model - those live on your sampler and checkpoint nodes, and this node refuses to guess a value that would travel with the image as if it were true. Your save node has to contribute the sampler settings.
How to install it
ComfyUI Manager can't find this pack yet - the registry flagged v0.1.1 on six severity: info pattern matches, so it's absent from Manager's search. That's a review hiccup, not a broken pack. The manual install works today:
cd ComfyUI/custom_nodes
git clone https://github.com/master-merlin/comfyui-mrln-nodes ComfyUI-MRLN-Nodes
Restart ComfyUI. No extra Python dependencies - requirements.txt is deliberately empty, and the features that touch images use Pillow/PyYAML through soft imports that ComfyUI already ships.
Common issues
- New templates don't show up - hit "Refresh node definitions" after adding library files.
- "selection references unknown slot(s)" - you switched templates and left selection lines from the old one. Remove them or re-apply from the Composer.
- Combinatorial mode errors - it names the computed size when you're over the 512 cap; fix more slots in the selection box.
- Seed discipline - the
seedwidget hascontrol_after_generatelike every ComfyUI seed: the number shown is what runs next, not what just ran. Worth setting widget control mode to "Before" once per install.
The pack is a first release, so don't expect a wall of community workflows to crib from yet - the 100 shipped templates are the tutorial.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| template | COMBO | Template from the prompt library (factory + user merged; a user file with the same slug overrides factory). New files appear after 'Refresh node definitions'. | |
| template_names | COMBO | slug | How the template widget above names templates. 'slug' is the file path — the stable identifier, and what a shared workflow should carry. 'label' lets the widget hold the human name instead (the Composer's Apply to node writes that form), which reads better but breaks if the label is edited or a second template takes it. Either way a value that IS a known slug is read as one, so nothing already saved changes meaning. |
| trigger | STRING | Value for the {trigger} variable — usually your LoRA trigger word or the subject line (e.g. 'BMWM4CS_G82'). Type it here or connect a STRING output from another node. | |
| selection | STRING | Per-slot overrides, one 'slot=item' per line. 'slot=random' rolls the slot with the master seed, 'slot=random@123' with its own seed; 'slot=off' mutes the slot entirely; 'variant=<name|random|off>' picks or mutes the variant branch. Blank lines and # comments are ignored; unlisted slots use template defaults. | |
| selection_mode | COMBO | Master switch. 'as configured' honors each slot's fixed/random mode; 'randomize all' rolls every slot (and the variant); 'all fixed defaults' pins every slot to its template default. | |
| seed | INT | 00–18446744073709550000 | Master seed for all random slots. Same seed + same library files = identical result; each slot draws independently, so fixed slots stay constant while random ones vary with the seed. Connect the same seed source as your sampler for lockstep. |
| format | COMBO | Output format override. 'string' joins everything into one line; 'string_labeled' emits 'Label: text' lines; 'json' emits one key per slot; 'json_flat' wraps the string render as {"prompt": ...}. Negative output is always a plain string. | |
| text_length | COMBO | Which item texts render: 'long' full descriptions, 'short' compact variants for tight tokenizers (e.g. SDXL). Items without a short text fall back to their long text. Draws are identical either way. | |
| conflict_policy | COMBO | When a negative term also appears in the rendered prompt: 'negative prevails' keeps it in the negative output, 'positive prevails' drops it (a drawn section explicitly wants the term). Conflicts are always listed in the choices report. | |
| variablesopt | STRING | Extra template variables as 'name=value' lines. Each line fills the matching {name} placeholder in the template's prefix/suffix and item texts — e.g. 'plate=MRLN 500' sets the license plate caption {plate} in overdrive/full-shot. The template's Composer view lists which variables it declares. | |
| profileopt | COMBO | standard | Target-model profile: applies that profile's render overrides (format/text length) and emits its LLM system prompt on the llm output. 'standard' = the template's plain render. Profiles come from profiles.json (factory + user tier) extended by the template's own; explicit format/text_length widget choices still win. |
| batch_countopt | INT | 11–64 | How many prompts this node emits per queue — the fix for 'batch size 4, four identical images'. Every output becomes a LIST of that many prompts and ComfyUI runs the downstream graph once per item, so each image gets its own draw. Item i uses master seed + i, so fixed slots stay put while random ones vary. 1 (the default) is exactly the single value this node has always emitted — existing workflows are unaffected. IGNORED in 'combinatorial' mode, where the number of combinations sets the count. |
| batch_modeopt | COMBO | increment seed | How the batch varies. 'increment seed': render batch_count prompts with master seeds seed, seed+1, seed+2 … — the usual 'give me N different ones'. 'combinatorial': ignore batch_count and emit EVERY combination of the slots that are currently random, in template order, each one pinned (they report as [fixed], and the batch line names the enumerated slots); leftover randomness such as a random variant stays on the master seed. Capped at 512 combinations — over that it errors with the computed size, and you shrink the space by fixing more slots in the selection box. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| prompt | STRING | The rendered positive prompt in the chosen format. |
| llm | STRING | The 'Prompt Enhance (MRLN)' single wire: {target, prompt, protect, system, params} — the rendered prompt, the profile's LLM system prompt, and the LoRA trigger words the enhancer must keep verbatim. |
| loras | STRING | JSON list of the drawn LoRA blocks (file + strengths) — wire into the 'LoRA Apply (MRLN)' node between your model/clip loaders and the sampler. |
| negative | STRING | The joined negative prompt (template + section + item negatives), always a plain string. |
| choices | STRING | Report of the variant/items chosen per slot with seed and tier — wire to a text preview to see what was drawn. Batched runs prefix each item with a 'batch i/N (seed …)' line. |
| gen_info | STRING | Generation metadata in the A1111 'parameters' dialect, for a save node that can embed a metadata string: the positive prompt, a 'Negative prompt:' line when there is one, then 'Seed: <seed>' plus 'Civitai resources:' naming the drawn LoRAs by Civitai model-version id and weight (LoRAs without a Civitai AIR are left out). INCLUDED is only what this node knows — there is deliberately NO Steps, Sampler, CFG scale or Model here, because those live on your sampler and checkpoint nodes and a guessed value would travel with the image as if it were true. Civitai's own reader needs a 'Steps:' key before it looks at any of this, so the save node has to contribute the sampler settings on the same key/value line. This pack writes no images. |