Storyboard · Frame Grid
Plan the whole shot list before you generate a single frame
- prompt
- name
- aspect_ratio
- frame_index
- frame_count
- width
- height
- all_prompts
You've got a ten-shot sequence in your head and no desire to build ten CLIP Text Encode nodes, ten EmptyLatentImage nodes, and a mental spreadsheet tracking which prompt goes with which resolution. That's the job FrameGrid exists for. It's the pre-production node: you type your shot list once - name, prompt, aspect ratio per frame - and it hands you the active frame's prompt plus the width/height integers you need to generate it.
It's the flagship of Storyboard Suite (repo: Smyshnikof/comfyui-storyboard-suite), a small, dependency-free pack of "planning" nodes from @itsmyshnikov. No GPU, no model, no API key. It's a glorified spreadsheet wearing a ComfyUI skin, and that's the whole point: the pack's framing is that deciding what you're going to generate before you generate it should happen inside the graph, not in a separate doc you'll lose.
How it works
The frames_data widget holds a JSON array - each frame is an object with an id, a name, a prompt, and an aspect. A select value picks the active frame, and the node computes its resolution from the aspect ratio: the long edge is set to base_resolution, the short edge is proportional, and both are rounded down to a multiple of 8. That rounding is why you get clean numbers like 1024×576 instead of 1024×438.86 - they drop straight into EmptyLatentImage.
The real magic is in the web frontend. The JSON is hidden behind a drag-sortable card grid with an aspect dropdown per card, so you reorder shots by dragging instead of hand-editing a blob of text. The node accepts plain pipe-separated text too (name|prompt|aspect), so even if the JSON widget gets mangled in a workflow file, it still parses.
The inputs that matter
- frames_data - the shot list itself. Multi-line JSON, one object per frame. This is what you'll spend your time on.
- select - which frame is active. Matches by name (case-insensitive) or by index; default is
"0". The UI renders this as a dropdown of frame names. - base_resolution - the long edge in pixels, default 1024, range 512–2048. This sets the "size" of your whole storyboard.
- default_aspect - the fallback aspect for frames that don't set their own. 13 presets from
21:9to9:21. - columns - display-only. It controls how many cards per row in the node's grid and doesn't touch the math.
The outputs that matter
FrameGrid is a single-frame node, so pick one frame and read its data:
- prompt, name, aspect_ratio - the active frame.
- width, height - INT, multiples of 8, ready for
EmptyLatentImage. - frame_index, frame_count - where you are in the sequence.
- all_prompts - every prompt joined with
\n---\n, handy if you want a text overview of the whole board in one string.
Wire width/height → EmptyLatentImage, prompt → CLIP Text Encode, and you've got one shot rendered. The pack's example workflow does exactly this with SD1.5 and expects v1-5-pruned-emaonly.safetensors.
Install
Two ways, both painless. The pack has no dependencies - requirements.txt is effectively empty and nothing installs into your Python env, which is a rare treat given the usual dependency hell in this ecosystem.
ComfyUI Manager - search "comfyui-storyboard-suite" and install, then restart:
cd ComfyUI/custom_nodes
git clone https://github.com/Smyshnikof/comfyui-storyboard-suite
Restart ComfyUI, then right-click → Add Node → Storyboard. No models to download.
Gotchas
selectbinds by name. Drag-sort reorders the cards, but the active frame follows its name, so reordering won't silently swap the frame you're looking at. The flip side: rename a frame and a selection pointed at it quietly falls back to the first frame.- Because dims round down, a
21:9frame at base 1024 comes out 1024×432, not the exact 438.9 - close enough, but don't expect pixel-perfect ratios. - It's a brand-new, small pack. If the fancy panel doesn't render after install, hard-refresh the browser; the raw JSON widget underneath still works, so you're never fully stuck.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| frames_data | STRING | [ { "id": "frame-1", "name": "opening", "prompt": "wide establishing shot, city skyline at dawn", "aspect": "16:9" }, { "id": "frame-2", "name": "hero", "prompt": "medium shot, protagonist walking through crowd", "aspect": "16:9" }, { "id": "frame-3", "name": "detail", "prompt": "close-up on hands holding a letter", "aspect": "9:16" } ] | — |
| select | STRING | 0 | — |
| base_resolution | INT | 1024512–2048 | — |
| columns | INT | 31–6 | — |
| default_aspect | COMBO | 16:9 | 13 options: 21:9, 16:9, 16:10, 3:2, 4:3, 5:4, +7 |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| prompt | STRING | — |
| name | STRING | — |
| aspect_ratio | STRING | — |
| frame_index | INT | — |
| frame_count | INT | — |
| width | INT | — |
| height | INT | — |
| all_prompts | STRING | — |