MOSS Layout Editor
Drag the boxes where you want them, then generate
- prompt
- width
- height
- spec
- template
- report
- negative
Describing a poster in prose is a losing game. "Title top left, character centre-right, subtitle band across the bottom" - you write it, you get approximately that, you reword it, you get something else. Layout is the part you have a real opinion about, and words are a bad interface for geometry.
This node gives you a canvas. Draw a rectangle where the title goes, another where the subject goes, type what each says, and it compiles a MOSS layout prompt plus canvas dimensions. No model, no sampling - instant.
Two modes, one state
The node has one input, editor_state, and you don't type into it: it's the canvas's save file, a v3 JSON blob that rewrites itself when you drag a box. Hand-editing works, but fields must match the v3 contract or it errors and names the field.
The preset decides what the node emits:
Poster mode - two-column, stacked, title-plus-subject-plus-body, three-way split, centred, layered, blank. Each box becomes an item in a multi-element layout JSON; prompt outputs it ready for a CLIPTextEncode.
Grid mode - the storyboard preset. prompt comes out as a [STYLE] paragraph plus [PANEL n] segments, so it drops straight into the Sampler's positive, and spec is populated for the Sampler, Crop and Paste.
That carries into the other outputs: poster mode gives an empty spec - no grid to cut - and a flat placeholder template; grid mode gives both for real.
The text element, and the trap inside it
Each box has a type - object, character, or text - and a caption. Text boxes get a second field, text, and mixing the two up is the node's classic mistake.
caption describes what the text looks like: "bold sans-serif headline, pale gold, slight outline." text is the words to render. Fill them backwards and you've asked the model to draw the words "bold gold" in an unspecified font.
And it's obedient here, which is the reason to use it: the author's tests show correct four-character Chinese and English headlines, mixed Chinese/English, respected line breaks, and a specified hex colour.
Two limits. Box height doesn't control font size - a 43px-tall box produced ~130px glyphs that overflowed it; size follows box width and copy length. And don't put a text box near the edge: at 5% from the top, ascenders spilled out and got clipped, repeatably. Presets leave 10%, which is merely more conservative than 5%, not verified safe.
Using it as a poster pipeline
- Pick a preset, drag your boxes.
- Fill each box's caption; for text boxes fill
texttoo. prompt→CLIPTextEncode.text.width/height→ anEmptyFlux2LatentImage.- A normal
KSamplerafter it - 4 steps at cfg 1.0 with a 4-step distillation LoRA, or 30–50 steps at cfg 3–5 on official weights.
Step 5 has a warning attached: don't route poster mode into the Storyboard Sampler. That node looks for [PANEL n] segments, so an already-compiled layout JSON gets parsed twice. Poster mode goes through a plain KSampler; grid mode feeds the Sampler.
Canvas mechanics are what you'd expect and no more: drag empty space to make a box, drag box or corners to move and resize, snapping to other boxes, the midline and the thirds lines. Delete, arrow keys, Ctrl+D, Ctrl+Z / Ctrl+Shift+Z. ComfyUI's bounding-box plumbing is normally four loose integers fed to crop and region nodes; here the rectangle is something you can see and argue with.
Install
Manager, search MOSS Storyboard. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/ZenHG/ComfyUI-MOSS-Storyboard
Restart and look for [MOSS SB] v0.2.2 in the startup log. The pack installs zero pip dependencies by design - requirements.txt is empty so Manager skips pip; torch and comfy belong to the host. Host floor: ComfyUI ≥ 0.42.0. Generating from its output needs moss_image_sft_bf16.safetensors in models/unet/, qwen3.5_9b_int8_convrot.safetensors in models/clip/ (loader type moss_image), and flux2-vae.safetensors in models/vae/.
Where people get burned
The canvas or the 中/EN button doesn't appear after an update. Press F5, not restart - the frontend is a single-page app, so an open tab keeps running the old JavaScript.
Text rendered as garbage words. You put the copy in caption and the style description in text - or left text empty, so there's nothing to render.
Composition ignores the boxes. Layout adherence is officially experimental: the GUI hands over exact geometry, the model treats it as a strong hint. The author's testing shows it working - a bicycle went from cropped to present when its box moved - but three seeds isn't a guarantee.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| editor_state | STRING | {"version": 3, "preset": "free", "style": "", "blend": true, "items": [], "canvas": {"width": 1536, "height": 864}} | 【不用手填】编辑器的存档:整份布局状态序列化成的 JSON。 在节点里用画布改,这里会自动更新。 手改也行,但字段必须符合 v3 结构,否则会报错。 |
| promptopt | STRING | 【接线,可选】外接故事板稿:[STYLE] 全局描述 + 每格 [PANEL n] 描述。 接上就接管逐格描述(编辑器里的描述框变只读,预设文案会被覆盖),断开恢复手编。 画布、格数、每格坐标仍来自编辑器——外接稿只改文字。 段首写景别(如「中景,…」)会用外接的;没写则该格不注入景别。 段数不足时后几格沿用编辑器描述;多出的段被丢弃,都写进 report,不静默。 |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| prompt | STRING | — |
| width | INT | — |
| height | INT | — |
| spec | STRING | — |
| template | IMAGE | — |
| report | STRING | — |
| negative | STRING | — |