Extensions/ComfyUI-PerfectLab
ComfyUI Extension

ComfyUI-PerfectLab

Visual prompt builder for ComfyUI: lighting clock, camera & film, palettes, random categories, template forms and a Shot Series node that turns one person description into a whole photo session. SDXL / Flux / Z-Image / Qwen-Image / Wan.

By perfectmodelslab·Created 8 months ago·Updated about 12 hours ago· 1
perfectmodelslab/ComfyUI-PerfectLab
Nodes4
On cloudLocal install
CategoryPerfectLab
Stars1
Updatedabout 12 hours ago
Readme

🧪 PerfectLab — Prompt Assistant for ComfyUI

License: MIT Platform Release

<p align="center"> <img src="docs/02-node-form.png" alt="PerfectLab Prompt Assistant node: template form, lighting clock, camera, palette and categories, with the assembled prompt previewed in a text node" width="560"> </p>

An interactive visual prompt-builder node with a full-featured UI embedded directly in the ComfyUI canvas. Build cinematic, controlled prompts without touching raw text: pick lighting by hour of day, assemble a camera rig, enforce a color palette, and manage randomizable prompt categories with per-category lock/random modes.

The node includes a live preview of the final assembled prompt (connect the PROMPT output to a text preview node, as shown above).

Features

🕐 Lighting Engine

Interactive lighting clock: eight phases of day on a draggable dial

Select an hour of day with the slider or the interactive 24-hour clock and get a matching cinematic lighting description — from deep night to blue hour, golden sunrise to noir.

📷 Camera & Film Builder

Camera builder: device, vibe, lens, film and light columns

Mix device, vibe, lens, film stock and studio lighting into a single camera tag — Sony A7IV + Kodak Portra + Rembrandt lighting, a disposable cam with harsh flash, or anything in between.

🎨 Color Palette

Palette picker with modifiers and swatches

Pick up to 5 colors with modifier presets (Neon, Pastel, Matte, Metallic, ...) to enforce a color scheme.

🗂 Categories

Matrix view with search and usage counters

Your own wildcard-style prompt lists:

  • LCK (lock) — always uses the selected item.
  • RND (random) — picks a random item, driven by the node seed (deterministic and reproducible).
  • Matrix view with search, A-Z / usage sorting and usage counters.

Also

  • 🎞 Variations — the variations input produces N seeded variations per run as a list (seed, seed+1, ...); ComfyUI iterates it downstream automatically — one run, a whole contact sheet of prompts.
  • ↔ NEGATIVE output — an optional second output with its own base text and categories, edited in the node's NEG tab. Leave it unconnected if you don't need it.
  • {a|b|c} dynamic choices — inline alternatives in the base prompt or in any category item, resolved from the seed (nesting supported).
  • {{name}} template fields — put {{outfit}} or {{mood|calm|stormy}} anywhere in the base prompt and a form field appears in the node: fill it with fixed text, or leave it empty with options to roll a fresh choice per variation.
  • 👤 Characters — save the current set of categories under a name and re-apply it to any node (or to the NEGATIVE tab) with one click.
  • 📁 Wildcard files — __filename__ in any text pulls lines from wildcards/filename.txt in the node folder; files are re-read when they change on disk.
  • 🔁 Campaign mode (CYC) — a category can advance to its next item every N seeds instead of rolling, so a seed range walks through a whole list in order.
  • ⚠ Prompt linter — the badge in the header flags token overflow, duplicate items, unbalanced braces, pointless single-item randoms and an empty NEGATIVE.
  • ⬇ Category import — paste JSON or a markdown list, or copy the built-in LLM prompt, let a chat model split your idea into categories, and paste the result back.
  • 🌐 UI languages — the header button switches the panel between English, Russian and Chinese.
  • 🧩 Companion nodes — Concat merges two prompt streams element-wise, Split picks one line from a stream by index (negative index counts from the end). Both carry the same branded black panel as the main node.
  • 🖼 Restore from image — drag a PNG generated with this node onto it: the config is restored from the image metadata (ComfyUI workflow/prompt chunks).
  • 🔢 Live stats — token estimate per target model and total variation counter.
  • ↩ Undo / Redo — 50-step history for the whole node config.
  • 📂 Presets — save the current configuration as JSON, load by button or by dragging a .json file / PNG onto the node.
  • Model profiles — SDXL keeps tag/weight syntax (75-token scale); Flux, Flux/Z-Image, Z-Image Turbo, Qwen-Image and Wan (video) get natural-language cleanup (weights and brackets stripped) with per-model token limits.
  • 👤 Characters modal — save and re-apply whole category sets. Characters
  • ⬇ Import modal — paste JSON / markdown, or let an LLM split an idea into categories. Import
  • ⚠ Linter modal — the header badge collects everything worth fixing in one list. Prompt check

🎞 Shot Series node

🧪 PerfectLab - Shot Series builds a whole photo session from one person description. Like the main node it carries a branded panel: nine axis rows with live values, a numbered contact sheet showing what each framing looks like, and a grid of outfit demos — click one to copy its full structured prompt to the clipboard.

Shot Series node with the axis pin list open Describe the person once (connect any text — or two versions: a detailed one for close shots and a shorter one for wide shots), and the node walks through nine axes on its own:

  • Framing (7) · Pose (32) · Expression (28) · Focus (12) · Hair (24) · Outfit (14) · Footwear (12) · Lighting (8) · Format (7 aspect ratios).
  • Framing and aspect ratio stay coupled: close-ups land in 1:1 / 4:5 / 3:4, wide shots in 2:3 / 9:16 / 16:9 — always at the same ~1.5 MP pixel budget, snapped to /16.
  • The axes are counted, not rolled: every run takes the next step through each axis, so a series covers all framings without repeating and a given seed always produces the same session.
  • Outputs are lists — PROMPT, WIDTH, HEIGHT and SEED — so ComfyUI's list handling iterates the whole session downstream; no queue scripts needed.
  • Every axis can be pinned: click a row to unfold its value list and pick one — the remaining axes keep walking. Shoot one look from seven framings, or one framing in twelve poses, without editing a single text field.
  • The template field lets you rearrange the sentence ({framing} of {person} in {scene}, {pose}...) — all thirteen keys, including {hair}, {outfit}, {footwear} and {lighting}, can move or drop out.

Installation

No third-party Python dependencies — requirements.txt is intentionally empty.

Via ComfyUI-Manager (easiest)

Open Manager → Custom Nodes Manager → Install via Git URL and paste:

https://github.com/perfectmodelslab/ComfyUI-PerfectLab

Manual

cd ComfyUI/custom_nodes
git clone https://github.com/perfectmodelslab/ComfyUI-PerfectLab PerfectLab

Then restart ComfyUI and hard-refresh the browser tab.

Troubleshooting

  • Node doesn't appear in the Add Node menu — fully restart ComfyUI (a running server only scans custom_nodes at startup), then hard-refresh the browser with Ctrl+F5. If it still fails, check the ComfyUI console for IMPORT FAILED or An error occurred while retrieving information messages mentioning PerfectLabAssistant.
  • Styles look broken / unstyled — hard-refresh with Ctrl+F5 to clear the cached stylesheet.
  • Folder name doesn't matter — any folder name works (PerfectLab is just the convention).

Tutorial

1 · Add the node and shape the prompt

Add 🧪 PerfectLab - Prompt Assistant, pick the target model profile (mode — Z-Image Turbo in the shot below), and write your base prompt. Anything wrapped in {{double braces}} becomes a form field below the header: fill it with fixed text, or leave it empty when the placeholder has options ({{city|Paris|Rome|Prague}}) and every seed rolls a fresh choice.

The assembled result is always one PROMPT output away — connect it to any text preview to see exactly what the sampler receives.

The Prompt Assistant node with the form, lighting, camera and categories

2 · Light it by the clock

Turn LIGHTING on and drag the slider — or open the clock with the ◷ button. Each hour maps to a written lighting paragraph (eight named phases from deep night to golden hour), so the light in the prompt matches the time of day instead of vague keywords.

The lighting clock

3 · Camera, film, palette

CAMERA opens a builder with five columns — device, vibe, lens, film, light — that compose one camera line. PALETTE picks swatches plus modifiers (Neon, Pastel, Metallic...) and steers the color words in the prompt.

The camera builder

4 · Categories: the randomizable parts

Categories are your own lists — and you don't have to start from scratch: + ADD opens the category library with pre-filled shoot-plan groups (Person, Outfit, Scene, Mood & Camera — hairstyles, footwear, locations, film looks and more). One click adds a ready category; edit its items afterwards like any other.

Category library

LCK always uses the selected item, RND rolls from the seed (deterministic — same seed, same pick), CYC advances to the next item every N seeds and walks the list in order. The ⊞ matrix gives you search, A-Z / usage sorting and per-item counters; the ⚠ badge in the header is a linter that flags overflow, duplicates and empty fields.

Matrix view

5 · The NEGATIVE tab

Switch to NEG to give the optional second output its own base text and categories. Leave it unconnected if your model does not use negatives.

The NEGATIVE tab

6 · Shot Series: one person, a whole session

Describe the person once (or two versions: detailed for close shots, compact for wide ones), connect any scene text, and the Shot Series walks through nine axes on its own — framing, focus, pose, expression, hair, outfit, footwear, lighting and aspect ratio. Outputs are lists — PROMPT, WIDTH, HEIGHT, SEED — so one node queues the whole session through ComfyUI's list handling: feed WIDTH/HEIGHT into an empty latent and let it iterate.

The panel has the nine axis rows (click a row to unfold its value list and pin one — the rest keep walking), a clickable contact sheet — select a shot to see what the framing covers and which ratios it lands on — and outfit demos: click a look, the preview card shows it and copies its full structured prompt.

The Shot Series panel with the hair axis pin list open

7 · Companion nodes

Concat merges two prompt streams element-wise (a length-1 list broadcasts across the merge — one style line for every shot), Split picks one line by index — negative indexes count from the end. Together with the main node they cover most prompt-plumbing cases without extra glue nodes.

Concat and Split

Demo sets

The previews inside the nodes are static samples, shot on Z-Image Turbo (JW Face / Z-Detail / Z-Light community LoRAs, fixed seeds) so every user sees the same reference. The full-resolution sets live in docs/examples/ — same images as the ribbons below, one row per preview.

The framings the Shot Series walks through:

The seven framings ribbon

The outfit demos shipped in the panel:

The outfit demos ribbon

And the lighting clock, one scene at four hours:

The lighting ribbon

<details> <summary><b>Full-size demo sheets</b></summary> <br>

One scene, four hours

What a series looks like

</details>

Ready-made presets

Eight starter presets are bundled in the presets/ folder — drag any of them onto the node to load it:

| Preset | Mood | |---|---| | cinematic_night_city | Neo-noir night streets, teal & orange, anamorphic | | golden_hour_portrait | Sunset editorial portraits, Portra 400, Rembrandt light | | amateur_selfie | Realistic casual smartphone snapshots, harsh flash | | cyberpunk_street | Neon cyberpunk, vaporwave, holographic ads | | vintage_film | 1970s analog film, Helios swirly bokeh, faded colors | | product_studio | Clean commercial product shots on studio backdrops | | video_shot | Video shots for Wan-class models: camera moves + motion details | | person_studio | Person sheets for the Shot Series node: looks, hair, eyes, outfits |

A minimal schema example is also available in examples/example_preset.json.

Preset format

{
  "time_of_day": 19,
  "palette": ["Neon Pink", "Neon Blue"],
  "camera": "Sony A7IV, Rembrandt Lighting",
  "style": {
    "active": true,
    "mode": "RND",
    "items": ["cyberpunk style", "vaporwave aesthetic"],
    "selected": "cyberpunk style"
  }
}

Any number of category keys is allowed (active, mode (LCK/RND), items, selected). Use "time_of_day": -1 to keep lighting off.

License

Distributed under the MIT License.