Comfy-Org / Comfy-Org/workflow_templates
Committed hub-media JPEGs are larger than the Cloudflare transform at every width — keep or drop the image pipeline?
- Dominant language
- TypeScript
- Stars
- 901
- Forks
- 188
- Avg merge
- 23h 10m
- Merged PRs (30d)
- 86
Description
Follow-up from #1216 (GTM-265). Not a defect — a design question the PR left unrecorded, with numbers.
## The question
#1216 added two things that solve the same problem for still images:
1. **A generated-copy pipeline.** `site/scripts/hub-media/encode-images.mjs` re-encodes stills to JPEG at up to 2048 wide, uploads them, and records them in `site/src/data/hub-media-images.json` (329 assets). `hubImageFor()` rewrites card and hero URLs to those copies.
2. **A Cloudflare transform.** `getStillImageUrl()` in `site/src/lib/video-thumbnail.ts` builds a `cdn-cgi/image/width=N,anim=false,format=auto,quality=82` URL on the same `comfy-hub-assets.comfy.org` origin. It is currently the *fallback*, used only when an asset has no generated copy.
The fallback appears to beat the primary at every width.
## Measured
40 of the 329 committed images, each fetched three ways:
| | bytes |
| --- | ---: |
| our committed JPEGs | **7.26 MB** |
| `cdn-cgi/image` at the *same* 1920 width | **5.74 MB** — 21% smaller, and smaller on **39 of 40** |
| `cdn-cgi/image` at 640, the width cards actually render into | **1.60 MB** — 78% smaller |
The transform negotiates format per request: AVIF for 29 of the 40, WebP for 11. Our copies are JPEG only, one size, no negotiation.
## Why this is worth deciding rather than leaving
The transform needs no bucket, no manifest, no regeneration step, and no "regenerate immediately before shipping" caveat in the runbook. It cannot go stale against a workflow uploaded after the last run, which is the failure mode `hub-media-images.json` is explicitly designed around. And #1216's own "still open" list already names the residual `uses-responsive-images` waste — 502 KB on the use-case detail page — as coming from *our own single-size copies*.
## The counter-argument, which may well win
Cloudflare bills image transformations per unique transformation. 329 assets × the widths we would serve is a real, recurring cost, where the committed copies are paid once. There may also be a reason to not depend on the transform for the hot path. Either is a fine answer — it just is not written down anywhere, and the numbers above suggest the current arrangement is the more expensive one in bytes.
## Ask
Decide one of:
- **Keep the copies** and record why in `site/scripts/hub-media/README.md`, so the next person does not re-derive this.
- **Drop the image half** of the pipeline (`encode-images.mjs`, `hub-media-images.json`, the `hubImageFor` call sites) and let `getStillImageUrl` serve stills, sized per call site. The video half is unaffected and clearly justified — Cloudflare does not transcode video here.
Related: the responsive-`srcset` attempt #1216 describes as tried-and-reverted is downstream of this decision, since sizing per call site is most of that work.
Filed while reviewing #1216. Sample script and per-asset numbers available on request.
Contributor guide
No contributing guide indexed for this repository
Research direction
Read site/scripts/hub-media/README.md, encode-images.mjs, site/src/data/hub-media-images.json, and getStillImageUrl() in site/src/lib/video-thumbnail.ts. Compare the measured transfer savings with the Cloudflare transformation cost, then decide whether to document keeping the copies or remove the image pipeline and its hubImageFor call sites; the video pipeline remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- performance, web-dev
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100