MOSS Layout Editor
Stop Describing Where Things Go — MOSS Layout Editor Lets You Draw It
- layout
- width
- height
MOSS Layout Editor is a rectangle-drawing canvas bolted onto a ComfyUI node. You drag boxes for characters, objects and text, type a description into each, and the node hands a structured layout to an LLM formatter that compiles it into a MOSS prompt. It does not call an API, it needs no key, and it generates exactly zero images on its own.
Why bother? Because describing where things go in prose is a losing game. Conditioning applies to the whole canvas, so two characters in one prompt swap hair colours and clothing, and no amount of careful wording fixes it - that's the two-year-old complaint behind every regional prompting tool. Better encoders softened it; bounding boxes as part of the prompt schema, the way Ideogram 4 does it natively, is the more honest answer. MOSS is a model trained to read boxes, and this is the editor for handing it some.
How it works
It's a UI node with one input: layout_state, a single-line string of JSON holding version, width, height, summary, items[] and strict_validation. The bundled frontend widget rewrites that string every time you drag a box. On execution the node parses it, validates it, strips the editor-only bookkeeping (element IDs, stray text fields) and emits a clean draft. No thinking happens here.
Wire layout into LLM Xml Prompt Formatter's layout input and set that node's mode to MOSS. Get the mode wrong and execution stops with an error telling you so. The formatter appends your layout plus a firm instruction block to user_text, then a remote service compiles it - compile_moss_prompt converts your pixel coordinates into whatever coordinate space MOSS expects. You never convert by hand. That tool is required in MOSS mode at every effort level, including Close, so an unreachable service means an error rather than a half-finished draft. Expect a slow first call; it's a Hugging Face Space with the usual 30–60 second cold start.
What you actually edit, and what comes out
Everything lives on the canvas, not in fields. Canvas width and height must be positive multiples of 16 and are your generation resolution - resizing rescales the boxes proportionally. The global description is required. Each element is character, object or text, with a description and a pixel bbox (top-left origin, xyxy); text elements also need the literal string to render, punctuation and line breaks intact.
Draw a box with 画框, or type exact coordinates with 坐标新增. Shift-click or tick boxes to multi-select, then align left/centre/right or distribute evenly (three boxes minimum, and only if there's room). 严格校验布局 (strict validation) is on by default: it checks the LLM kept your canvas size, element count, order, types, boxes and text verbatim, so a model that helpfully nudged a rectangle gets caught instead of quietly ruining the composition. Turn it off and compile-side legality still applies, but the model can legitimately resize the canvas - read the real size from text_out and match it.
Three outputs: layout (type MOSS_LAYOUT) to the formatter, plus width and height as plain INTs for your latent or resolution inputs, so the two can't drift apart.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/SuzumiyaAkizuki/ComfyUI-LLM_Prompt_XML_Formatter
cd ComfyUI-LLM_Prompt_XML_Formatter
cp LPF_config.json.example LPF_config.json
In ComfyUI Manager, search NewBie-LLM-Formatter - registry name and repo folder disagree, so it isn't listed where you'd look. Fill in api_key and api_url (OpenAI-compatible, ending at /v1), add your models to model_list, restart, then hard-refresh the browser: the editor is frontend code, so a stale cache shows you an old node. Dependencies are light - openai, lxml, numpy, Pillow, httpx - and there are no model downloads. It's filed under the NewBie LLM Formatter category, not the image ones.
Where people get burned
The node works, the formatter doesn't. Most "it's broken" reports are config reports: no LPF_config.json, or a key typed into the formatter's UI field. Config values win over UI values, and a key typed into the UI gets saved into your workflow - share that PNG and you've shared the key.
You moved one box and paid for a whole new generation. The layout fingerprint covers every bbox, so any edit invalidates the cache and re-calls the LLM. Nudging a rectangle costs a request.
The image ignores your boxes. Boxes are a composition constraint, not a promise; adherence is the model's call. Text elements are fussiest, since the string has to survive both the LLM and the sampler.
You're early. Community chatter about MOSS is effectively nil - I found under sixty mentions of the term across the 2026 threads and none past July. The tooling exists; a shelf of other people's working workflows doesn't yet.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| layout_state | STRING | {"version": 1, "width": 1024, "height": 1024, "summary": "", "items": [], "strict_validation": true} | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| layout | MOSS_LAYOUT | — |
| width | INT | — |
| height | INT | — |