π§© Layer Manager
Layer Manager β the closest ComfyUI gets to Photoshop layers
- L1_image
- L1_mask
- image_bg
- image_rgba
- alpha
Here's the honest framing: compositing multiple images in plain ComfyUI is a pile of Mask, Blend and Composite nodes wired in the right order, and the moment you want to move one element six pixels, you edit a number and squint at the output. Layer Manager is the pack's flagship precisely because it refuses to make you do that. It's a multi-layer compositor with a real canvas editor - up to 20 layers, each with its own image/mask pair, drag-to-move, rotation, scaling, blend modes, opacity, ordering - that runs as a pop-up app while the node itself stays a tiny box on the graph.
How it works
The pattern is the pack's signature: a lightweight node plus an external editing window. The node exposes canvas_width, canvas_height, a background color, and a layer_config STRING that looks like {} but is actually the serialized brain - position, scale, rotation, opacity, blend mode, layer order, anchor, solo/lock/mute state. When you edit in the app, that JSON gets written back into the hidden widget, and the Python backend parses it and composites the layers for real. Nothing about the fancy editor is baked into the frontend canvas - which is also why this one holds up under the Nodes 2.0 frontend rewrite that broke a lot of legacy custom nodes.
Layer inputs are L1_image/L1_mask and the node grows more pairs dynamically up to L20. There's a dedicated invert_input_masks toggle because ComfyUI's mask convention (white = keep) is the opposite of what the compositor wants internally - if your masked layer comes out backwards, that's the switch. The flatten_output toggle decides whether image_bg composites the result onto the bg_hex color or keeps it as a pure flattened RGB pass.
The inputs that matter
L1_image/L1_mask- your first layer pair. Add more as L2, L3, β¦ up to 20.canvas_width/canvas_height- composite canvas size, 16β8192 (defaults 1024).bg_hex- background color for the flattened output (default white).layer_config- the hidden JSON. You can hand-edit it to script exact transforms, but 99% of the time the app writes it for you.invert_input_masks,flatten_output- the two behavior toggles above.
Outputs
Three: image_bg is the flattened RGB result, image_rgba is the composited RGBA with true transparency, and alpha is the final mask. For compositing onward, image_rgba is the one; for saving or feeding a model, image_bg.
The editor, briefly
In the app you can drag layers on canvas, scale from four corners, rotate with the handle, and control position/scale/rotation/opacity numerically. Blend modes, ordering, visibility, lock/mute/solo, anchor point, fit-to-canvas and nine-position alignment are all there, plus the little conveniences that make it feel like real software: mouse-wheel zoom, a hand tool (hold Space), and 36 levels of undo/redo (Ctrl+Z, Ctrl+Shift+Z/Ctrl+Y). Locked layers stay visible but get skipped during canvas hit-testing - clicking through one selects the first editable layer underneath, which is the right behavior even if it surprises you the first time.
Install
No models, no extra Python deps - just what a standard ComfyUI already ships:
cd ComfyUI/custom_nodes
git clone https://github.com/orion4d/Orion4D_layer_manager
Restart ComfyUI. Manager users: search Orion4D_layer_manager under "Install Custom Nodes."
Common issues
- Masked layer preview isn't accurate. The README is explicit: a workflow run may be required before an exact masked-layer preview appears in Layer Manager. Run once, then trust what you see.
- App window won't open. Pop-ups blocked - allow pop-ups for your local ComfyUI address.
- Slow with big layers. The pack documents that large canvases and many high-res layers increase processing time and memory. Keep the canvas at working size, not 8K, and upscale the final composite.
- Layer count cap. 20 pairs, no more. If you need 30, that's a workflow split, not a setting.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| canvas_width | INT | 102416β8192 | β |
| canvas_height | INT | 102416β8192 | β |
| bg_hex | STRING | #FFFFFF | β |
| flatten_output | BOOLEAN | true | β |
| invert_input_masks | BOOLEAN | false | β |
| layer_config | STRING | {} | β |
| L1_imageopt | IMAGE | β | |
| L1_maskopt | MASK | β |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image_bg | IMAGE | β |
| image_rgba | IMAGE | β |
| alpha | MASK | β |