Nodes/Palette Director/Palette Director
ComfyUI Node

Palette Director

Palette guidance before the model draws a single pixel

By SKBv0·Created 3 months ago·Updated 2 months ago· 10
Palette Director
  • clip
  • palette_image
  • positive
  • negative
  • full_prompt_debug
  • palette_report
promptcinematic product photo of a futuristic sneaker on a clean studio plinth
negative_prompt
palette_hex#111111 #2B2B2B #EDEDED #FF3158 #13D8C8
role_hex
weights0.34 0.24 0.18 0.14 0.10
layoutas_written
card_size1024
palette_hex_input
role_hex_input
weights_input

Say the words "make it red and cream" and a Flux model half-listens, then gives you whatever it feels like. Palette Director tries to pin the vibe down before sampling by handing the model a picture of your palette - the "palette card" - plus a structured prompt suffix that names which color does what. It's guidance, not a guarantee - and it only works if you also load its companion LoRA.

That last part is the headline: on a normal model, this node adds essentially no color control. It prepares conditioning for a palette-trained LoRA. The author tested it against the Flux.2 Klein "Palette Director v1.0" LoRA from Civitai on the flux-2klein-9b-kv-fp8 checkpoint. Without that LoRA loaded, you're feeding a model a format it never learned.

How it works

The node does three concrete things. First, it parses your hex colors and weights and builds the palette-card image - a square (default 1024, from 256 to 2048). The left ~70% is a row of color bars whose widths match your weights; the right ~30% is five stacked role swatches in the fixed order bg, main, human, material, accent. Second, it builds a prompt suffix in the exact format the LoRA was trained on, something like palette_control bg=#111111 main=#2B2B2B ... weights=#111111:34% ... use_palette_roles. Third, it encodes your prompt plus that suffix through the CLIP you hand it, producing real CONDITIONING outputs.

A couple of details worth knowing:

  • The layout enum (as_written, dark_to_light, light_to_dark, mixed, shuffle) reorders the card's color bars. shuffle is seeded from the palette text, so it's deterministic - it won't change every run.
  • The suffix only goes into the positive. Your negative_prompt is encoded as-is, no palette chatter.
  • full_prompt_debug shows the exact final prompt; palette_report is a readable summary. Wire one to a preview when you're debugging.

Inputs that matter

Most fields are self-explanatory, but a few deserve attention:

  • palette_hex - space-separated hex colors, at least 4 of them. Invalid values like #1234567 are rejected outright rather than silently ignored, so a typo fails loudly.
  • weights - relative weights, space-separated, matching the color order. They get normalized internally.
  • role_hex - optional, exactly 5 colors in role order. The tooltip says it plainly: leave it empty and the first 5 palette colors are used.
  • clip - required, and needs to be the Flux.2 Klein CLIP, since that's what the LoRA speaks.
  • The optional palette_hex_input / role_hex_input / weights_input are where you connect the Palette Composer node's outputs, if you don't want to type hex by hand.

Wiring it into a Flux.2 Klein graph

The outputs slot into a standard reference-latent setup. The README's own flow:

  • palette_imageVAEEncodeReferenceLatent attached to your sampling latent (the example attaches it to both positive and negative)
  • positive → your guider's positive input
  • negative → your guider's negative input
  • Load the LoRA with a normal LoRA loader (the example uses LoraLoaderModelOnly) placed before the guider

There's a ready-made example at examples/flux2_palette_director_workflow.json - load it, pick your checkpoint, point the LoRA loader at your download.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/SKBv0/ComfyUI_PaletteDirector

Restart ComfyUI. Dependencies are just numpy, pillow, and torch, all already present. The only download is the LoRA: grab Palette Director v1.0 (Flux.2 Klein) from Civitai and drop it in models/loras. No API calls, no keys.

Where it falls over

The README is refreshingly honest about the failure modes:

  • It is not hex-precise. This is pre-generation guidance; the author contrasts it with post-process color transfer tools, which nail exact remapping but can't shape a scene before it exists.
  • Prompt color words win fights. A prompt that says "blue jacket" can override a warm red material role.
  • The card can leak into the render as blocks, stripes, borders, or UI-like shapes, depending on strength and sampler.
  • Object priors push back - skin stays skin-colored, sky stays blue, if the LoRA isn't trained hard enough.
  • Role names are hints. The model mixes them up.
  • A subtle trap from the README's own comparison: with the card and suffix still connected, LoRA strength 0 is not a clean baseline. If you're A/B testing the LoRA, disconnect the Director entirely.

If output ignores your palette: raise the LoRA strength, strip color words out of the prompt, try a different layout, and accept that some scenes just won't bend. It's an amateur's learning project, but for getting a Flux.2 Klein render to lean into a palette instead of ignoring it, it's a genuinely fun, dependency-light tool.

CategoryPalette Director

Inputs (11)

NameTypeDefaultDescription
clipCLIP
promptSTRINGcinematic product photo of a futuristic sneaker on a clean studio plinth
negative_promptSTRING
palette_hexSTRING#111111 #2B2B2B #EDEDED #FF3158 #13D8C8
role_hexSTRINGOptional 5 colors in role order: bg main human material accent. If empty, the first 5 palette colors are used.
weightsSTRING0.34 0.24 0.18 0.14 0.10
layoutCOMBOas_written5 options: as_written, dark_to_light, light_to_dark, mixed, shuffle
card_sizeINT1024256–2048
palette_hex_inputoptSTRING
role_hex_inputoptSTRING
weights_inputoptSTRING

Outputs (5)

NameTypeDescription
palette_imageIMAGE
positiveCONDITIONING
negativeCONDITIONING
full_prompt_debugSTRING
palette_reportSTRING