Nodes/ComfyUI-CivitAI-Publisher/CivitAI Publisher (Review Before Upload)
ComfyUI Node

CivitAI Publisher (Review Before Upload)

Publish to CivitAI from your graph — review first, token stays out of the workflow

By Hearmeman24·Created a day ago·Updated about 22 hours ago· 1
CivitAI Publisher (Review Before Upload)
  • image
  • video
  • post_url
  • status
  • details
title
tags
nsfwfalse
prompt_override
approval_timeout_minutes30
generation_prompt

The name undersells it. CivitAIPublisher isn't a "post this image" button - it's a review gate bolted onto the end of your workflow. The node walks back up the branch feeding it, finds every checkpoint, LoRA, and ControlNet that actually went into your render, hashes them to figure out which CivitAI versions they are, and then shows you the whole package - playable media, final prompt, resolved resources, per-LoRA strengths - inside the node itself. Only when you click Approve & publish does anything leave your machine. Your CivitAI token never appears in the workflow file at all.

Why you'd reach for it

If you post your gens to CivitAI on the regular, you know the ritual: render, save, dig the metadata out of the PNG, open the site, fill the form, hand-type the resource list. This node collapses all of that into one step. An image batch plus an optional native ComfyUI video go up as a single post, with the model lineage attached automatically. It's the other end of the pipeline - the node that closes the loop from canvas to post without the copy-paste shuffle.

How it works

Under the hood it's two separate phases, and the split is the whole point. First, a read-only pass: it scans the ancestors of your connected image and video, collects the local file-backed weights (checkpoints, UNETs, LoRAs - including active rgthree Power LoRAs - ControlNets, embeddings, hypernetworks; it skips CLIP/VAE/preview/upscale aux weights), and hashes each file with SHA-256 in 8 MiB chunks. That hash is CivitAI's native identifier, so it can resolve each file to its exact CivitAI version. Results are cached in ComfyUI/user/.civitai-publisher/ - file identities in one JSON, version lookups in another - so re-running with a different prompt re-hashes nothing.

Then comes the review. The node renders an approval canvas in the browser: playable media, the prompt it intends to use, generation metadata, the resolved resources, and any local files CivitAI doesn't know. The browser never sees your token and makes no API calls. Approval is single-use and tied to one opaque execution id, so it can't authorize a later queue; reject, timeout, ComfyUI Stop, or a browser-less run all upload zero bytes.

The inputs that matter

The required five are all small:

  • title and tags - post title and comma-separated tags; both optional, blank is fine.
  • nsfw - flip it and the post gets flagged.
  • prompt_override - if you want a prompt that isn't the one detected from the graph, type it here.
  • approval_timeout_minutes - how long the review window stays open (default 30, max 240).

Two optional inputs are where the real wiring lives. image takes an IMAGE, video takes native ComfyUI VIDEO, and you can feed both. Then there's generation_prompt, and this is the gotcha most people will hit: the hidden ComfyUI API prompt is a graph description, not a record of runtime values. If your prompt comes from OpenRouter, Ollama, or another dynamic node, the publisher can't reconstruct it from the graph - so you connect that exact runtime STRING here. Precedence is nonblank prompt_override, then generation_prompt, then a literal prompt found on the media branch. A dynamic prompt with no explicit input fails before review rather than guessing from an LLM system prompt.

Outputs are three strings: post_url, status, and a compact JSON details you can inspect or log.

Install

ComfyUI Manager: search ComfyUI-CivitAI-Publisher. Or from the command line:

comfy node install comfyui-civitai-publisher

Manual install is the same as always - clone into ComfyUI/custom_nodes/ComfyUI-CivitAI-Publisher, then pip install -r requirements.txt. Dependencies are genuinely light: just aiohttp and Pillow. No torch extras, no model downloads.

The one thing you must do is put the token in the environment that launches ComfyUI, then restart:

export CIVITAI_TOKEN="your-token"

CIVITAI_API_KEY and the legacy lowercase civitai_token also work; CIVITAI_TOKEN wins.

Troubleshooting

  • Dynamic prompt without generation_prompt fails before review. This is by design - read the input above. It's the most common "why is my review empty" cause.
  • NSFW posts return a civitai.red/posts/<id> URL, not civitai.com/posts/<id>. That's CivitAI's NSFW serving domain, not a broken link. API traffic still goes to civitai.com either way.
  • Write steps aren't retried. Presign, upload, and post creation deliberately skip retries because a timed-out write may have already succeeded. If the post-creation call times out, the error includes a sanitized draft-post URL so you can recover.
  • It's brand new and one-person-maintained. Zero community signal out there as of writing, so audit the source before you hand it a token with write access - the same caution applies to any fresh node that carries a credential. The token is env-only and never sent to the browser, which is exactly the right shape; just keep the habit.

One more thing worth knowing: changing only your prompt doesn't re-read or re-hash your model files, and concurrent requests for the same unchanged file share a single in-flight hash. So iterate fast on wording - the expensive part only runs when a file actually changes.

CategoryHearmemanAI/CivitAI

Inputs (8)

NameTypeDefaultDescription
titleSTRING
tagsSTRING
nsfwBOOLEANfalse
prompt_overrideSTRING
approval_timeout_minutesINT301–240
imageoptIMAGE
videooptVIDEO
generation_promptoptSTRINGConnect the exact runtime string used by conditioning when the prompt comes from OpenRouter or another dynamic node.

Outputs (3)

NameTypeDescription
post_urlSTRING
statusSTRING
detailsSTRING