Elegant Nodes
Utility nodes built to work inside subgraphs: buttons, live results and previews stay usable on the subgraph node. A seed with random/fixed controls, an aspect-ratio resolution selector, plain-text previews and a math expression node.
Built for subgraphs
<img src="docs/images/subgraph.png" width="360" align="right" alt="One subgraph node with the seed buttons, the resolution result and the math preview">Subgraphs are great for packing a workflow into one tidy node, but buttons, live results and previews usually stay hidden inside, so you keep opening the subgraph to use or check them. ComfyUI's own Preview as Text, for example, shows nothing on the subgraph node.
Every Elegant node keeps working from the subgraph node. The node on the right is a subgraph holding an Elegant Seed, a Resolution Selector and a Math preview, used without opening it:
- Buttons: 🎲 Random, ♻️ Last seed → fixed and 🎲 Random → fixed act on the subgraph node's own seed.
- Live results: the resolution result updates as you change the promoted widgets.
- Previews: text and math results show on the subgraph node, and their last values are saved with the workflow, so they're there right after loading.
- Every copy of a subgraph keeps its own seed and shows its own values.
Nothing to set up: promote the widgets you want (ComfyUI promotes seed automatically), and
the rest follows. Demote them and it goes away.
The nodes

| Node | What it does | On the subgraph node | |------|--------------|----------------------| | Elegant Seed | A seed with a random/fixed switch and buttons to reuse or re-roll it. | Seed buttons, per copy | | Elegant Resolution Selector | Width and height from an aspect ratio, keeping the pixel count steady. | Live result | | Elegant Any to String Preview | Any value as plain text. | Text preview | | Elegant Any to String Multi Preview | Several values as text, joined with a delimiter. | Text preview | | Elegant Any Math Multi Preview | A math expression over any number of inputs, with a worked-out preview. | Worked-out result |
All nodes are in the utilities → elegant category. Click the cyan ? in a node's title for detailed help on that node.
Installation
ComfyUI-Manager: search for Elegant Nodes and click Install.
Comfy CLI:
comfy node install elegant-nodes
Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/wipeer/comfyui-elegant-nodes.git
pip install -r comfyui-elegant-nodes/requirements.txt
Restart ComfyUI and refresh the browser.
Requirements: ComfyUI 0.4.0 or newer (the nodes use the V3 node API with auto-growing inputs). The only Python dependency is simpleeval, which ComfyUI already installs.
Node details
Elegant Seed
Based on ComfyUI's built-in Seed node.
| Control | What it does |
|---------|--------------|
| mode | random: a new seed for every run. fixed: the seed in the field is always used. |
| seed | Shows the seed; type one to use it for the next run, in either mode. |
| 🎲 Random | New seed now, and switch to random. |
| ♻️ Last seed → fixed | Put back the seed the last run used and switch to fixed. The label shows that seed. |
| 🎲 Random → fixed | New seed, and switch to fixed. |
Outputs: seed (INT) and seed_text (STRING).
In random mode the node follows ComfyUI's setting Settings → Lite Graph → Node Widget →
Widget control mode:
- after (default): the run uses the seed you see, then a new one appears. To get back the seed of an image you liked, use ♻️ Last seed → fixed.
- before: a new seed is made just before the run, so the field shows the seed that was used.
The last seed is saved with the workflow. In a batch, every run gets its own seed and the last one is remembered. Random seeds go up to 2⁵³ − 1, the largest number the browser handles exactly (like ComfyUI's own randomize).
In a subgraph: seed is promoted automatically and the three buttons appear on the subgraph
node. Promote mode too to get the switch there; otherwise the switch inside is used.
Elegant Resolution Selector
| Control | What it does |
|---------|--------------|
| aspect_ratio | 1:1, 5:4, 9:7, 4:3, 3:2, 16:9, 21:9. In portrait the list shows them flipped (4:5 … 9:21). |
| orientation | landscape or portrait. No effect at 1:1. |
| base | Side of the square image. 1024 gives about 1 MP for every ratio (SDXL, Flux); 512 for SD 1.5. |
| round_to | Width and height become multiples of 8, 16 (default), 32 or 64. 16 suits Flux/SD3, 64 matches SDXL training sizes. |
| result | Read-only, live: e.g. 1360 × 768 · 1.00 MP · 1.77:1 (ratio after rounding; 1 MP = 1024 × 1024). |
Outputs: width and height (INT), e.g. into Empty Latent Image.
The size is width = base × √ratio and height = base ÷ √ratio, each rounded. At base 1024
and round to 16: 1:1 → 1024 × 1024, 4:3 → 1184 × 880, 3:2 → 1248 × 832, 16:9 → 1360 × 768,
21:9 → 1568 × 672.
In a subgraph: promote any of its widgets and the result field appears on the subgraph node, following the promoted values live.
Elegant Any to String Preview
Turns any value into text, shows it in a plain-text box you can select and copy, and outputs it
as string. Uses the same conversion as ComfyUI's
Preview as Text,
without the Markdown mode: text stays as is, numbers and booleans become their value, lists and
dictionaries become indented JSON, and anything else (tensors, latents, …) is printed.
In a subgraph: after each run the text also appears on the subgraph node, so you can check a value without opening it. The box is there as soon as the node is inside a subgraph, and the last text is saved with the workflow, so it shows again right after loading.
Elegant Any to String Multi Preview
The same for several values, joined with a delimiter.
source_1,source_2, …: a new input appears each time you connect the last free one (up to 20). Disconnect one and the gap closes.delimiter: default\n(new line).\tis a tab and\\a backslash; anything else is used as typed, e.g.,or|.
In a subgraph: the joined text appears on the subgraph node, like the single preview.
Elegant Any Math Multi Preview
Evaluates an expression over the inputs a, b, c, … and outputs the result as int,
float, boolean and string. The preview shows the expression with the real values filled in:
1 + (2 / 2) - 3 = -1
int -1
float -1.0
boolean True
string -1.0
- Inputs accept any type, and text that looks like a number is used as one. A new input
appears each time you connect the last free one (up to
z).valuesis the list of all inputs, e.g.sum(values). - Operators:
+ - * / // % **,== != < <= > >=,and or not,x if condition else y. - Functions:
sum min max abs round pow sqrt ceil floor log log2 log10 exp sin cos tan clamp int float str bool. Constants:pi,tau. - Outputs:
intcuts decimals off (1.77 → 1; useround(…)to round),booleanis False for 0 or empty text. If the result is text that isn't a number,intandfloatare 0. - Examples:
a / b,round(a / 64) * 64,max(a, b),a * b / 1048576(megapixels),clamp(a, 1, 150),a % 2 == 0,a + "_" + str(b).
Expressions are evaluated with simpleeval, like ComfyUI's own Math Expression node: only math, no Python code, and huge powers are refused. Errors such as division by zero or an unconnected input stop the run with a message.
In a subgraph: the worked-out result appears on the subgraph node after each run.
Help
Each node has a cyan ? in its title that opens detailed help, including every operator and function of the math node.
<img src="docs/images/help.png" width="560" alt="Help dialog of the math node">Upgrading from earlier versions
Version 1.0.0 renamed some node ids. Workflows saved with an earlier version show those nodes as missing; replace them with the new ones:
| Before | Now |
|--------|-----|
| Elegant Resolution (ElegantResolution) | Elegant Resolution Selector |
| Elegant Any to String (ElegantAnyToString) | Elegant Any to String Preview |
| Elegant Any to String (Advanced) (ElegantAnyToStringAdvanced) | Elegant Any to String Multi Preview |
Development
__init__.py ComfyUI entry point
nodes/ node definitions (V3 schema)
core/ logic without ComfyUI imports (resolution, text, math)
web/js/ frontend: buttons, live result, previews, help
tests/ pytest tests for core/
Run the tests (they need only simpleeval and pytest; Node.js enables one extra check):
pip install -r requirements.txt pytest
pytest tests
Releases are published to the Comfy Registry by GitHub Actions
when the version in pyproject.toml changes on main.