Nodes/comfyui-gcs-uploader/Upload to GCS πŸͺ£
ComfyUI Node

Upload to GCS πŸͺ£

This GCS uploader node is built for one pipeline β€” check if it's yours

By sumethweer-cmdΒ·Created 6 months agoΒ·Updated 6 months agoΒ· 0
Upload to GCS πŸͺ£
  • image
  • gcs_url
β—„job_idβ–Ί
β—„content_item_idβ–Ί
β—„image_typeβ–Ύβ–Ί
β—„slot_index0β–Ί

Let's be honest about this one up front: "Upload to GCS πŸͺ£" is not a general-purpose uploader that any ComfyUI user needs. It's a bespoke piece of one specific product - an "AI Influencer" SaaS that generates images on a RunPod-hosted ComfyUI and files them into a Supabase + Google Cloud Storage backend. The author wrote it to serve their own pipeline, it's a single-commit repo with essentially zero community footprint, and if you're not running that exact stack, the node will politely do nothing useful for you.

But if you are building the same shape of thing - ComfyUI headless on a rented GPU, a database telling it what to make, and finished images that need to land in object storage - it's a genuinely neat reference for a real problem. So here's what it actually does and how to make it work.

The mechanism (and the part worth stealing)

The whole pitch is one line from the README: zero Supabase Egress cost. The naive architecture routes generated images from your GPU box through a Supabase Edge Function into GCS, which bills you for ~4MB of egress per image. This node cuts that by uploading the pixels directly from ComfyUI to GCS, then sending only a small URL string to Supabase. Egress ~0. It's the same "the API node just sends a URL" pattern you see elsewhere in the ecosystem, but pointed at your own infra instead of a model vendor.

Under the hood it does five things in GCSUploadNode.upload():

  1. Loads config.json from the node's own directory for your Supabase URL + service role key.
  2. Fetches GCS credentials at runtime from your system_configs table (set in the web dashboard, not in the repo - that's why there's only one local config file).
  3. Converts the image tensor to PNG bytes.
  4. Uploads to images/{content_item_id}/{image_type}/{job_id}_{slot_index}.png in your bucket.
  5. Upserts a row into generated_images, marks the job Completed in production_jobs, and logs to system_logs. On any failure it flips the job to Failed with the error message.

The output is a single string, gcs_url, the public https://storage.googleapis.com/<bucket>/<path> - the thing your frontend or DB actually stores.

The inputs that matter

All five inputs are required, and honestly, three of them are boring plumbing:

  • image (IMAGE) - the tensor from your KSampler/VAE Decode. Note it grabs image[0] only, so in a batch of more than one frame, only the first frame gets uploaded. Fine for a content pipeline that generates one slot at a time.
  • job_id and content_item_id (STRING) - the production_jobs.id and content_items.id from your Supabase. These get injected per-run, typically by a String Literal / Load Text node or straight into the prompt payload when your system queues the job. The DB writes are keyed on them, so they're the fields you actually have to get right.
  • image_type (SFW/NSFW) and slot_index (INT, 0–16) - where in the product the image goes. slot_index just lands in the filename.

Installing it

ComfyUI Manager β†’ Install via Git URL β†’ https://github.com/sumethweer-cmd/comfyui-gcs-uploader, or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/sumethweer-cmd/comfyui-gcs-uploader
pip install -r comfyui-gcs-uploader/requirements.txt

Restart ComfyUI, then copy the config:

cd ComfyUI/custom_nodes/comfyui-gcs-uploader
cp config.json.example config.json

config.json is gitignored, so your key won't leak into a push. The dependencies are light - google-cloud-storage, requests, pillow - no model downloads, nothing heavy.

Where you'll get burned

The failure modes are all "bespoke pipeline" failures, and the code is honest about them:

  • No config.json β†’ it raises FileNotFoundError and tells you to copy the example. That's your first stop on any failure.
  • Missing GCS keys in system_configs β†’ explicit ValueError naming exactly which of the four (project ID, client email, private key, bucket name) is missing. The dashboard credentials have to be there, because there's no fallback.
  • Your Supabase tables must exist with the expected schema - production_jobs, generated_images, system_configs, system_logs. This node doesn't create them.
  • The service role key in config.json bypasses Row Level Security. That's a very privileged credential sitting in a file on your GPU box. Read the pack's source before running it anywhere you don't fully trust - a node that holds a key and phones home by design is exactly the category that's been weaponized before, so treat any fork of this the way you'd treat a sketchy API pack.

If you're not running the AI Influencer stack, skip it - but if you're wiring ComfyUI output straight into object storage, this is a clean, readable blueprint for doing it right.

CategoryAI Influencer / Storage

Inputs (5)

NameTypeDefaultDescription
imageIMAGEβ€”
job_idSTRINGβ€”
content_item_idSTRINGβ€”
image_typeCOMBO2 options: SFW, NSFW
slot_indexINT00–16β€”

Outputs (1)

NameTypeDescription
gcs_urlSTRINGβ€”