Skip to content

fix(core): use external image services for stored thumbnails - #2175

Open
masonjames wants to merge 1 commit into
emdash-cms:mainfrom
masonjames:codex/heic-media-support
Open

masonjames wants to merge 1 commit into
emdash-cms:mainfrom
masonjames:codex/heic-media-support

Conversation

@masonjames

@masonjames masonjames commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Stored-media thumbnails on Node fail when Astro uses an external image service: EmDash forwards the request to Astro's generic endpoint, which requires a local transformer. The endpoint now passes the storage adapter's public URL through the configured service's validateOptions and getURL, retaining replacement versions and revalidation headers. This allows existing HEIC media to render when the service supports it.

The fix requires a source URL the image service can reach. Upload acceptance is unchanged. It follows the maintainer's request to use the image server.

Type of change

  • Bug fix
  • Feature (requires an accepted feature plan or RFC)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Your connection to this change

  • I use EmDash and ran into the problem this PR addresses

This comes from stored-media previews on my EmDash site using Node, S3-compatible R2 storage, and an external image service.

  • I maintain a tool, dependency, or service that EmDash uses, and this change concerns that integration
  • A Maintainer approved this specific change before I opened the PR

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings are wrapped for translation — not applicable; no admin strings or catalogs changed.
  • I have added and reviewed the user-facing changeset (if this PR changes a published package)
  • New features link to their merged design PR — not applicable; this fixes the existing image endpoint.
  • I have included screenshots below if this PR changes the UI — rendered endpoint evidence is included; no admin components or layouts changed.

AI assistance disclosure

  • This PR includes AI-generated code or text — model/tool: OpenAI Codex (GPT-6); GPT-6.1-Sol for local browser verification; Claude Opus 5.5 for independent review.

Screenshots / test output

  • The new endpoint regressions failed before the fix. All 92 targeted endpoint, middleware, integration, and image-helper tests pass afterward.
  • pnpm format, root pnpm build, pnpm typecheck, pnpm lint:quick, and pnpm lint pass. Type-aware JSON lint reports zero diagnostics.
  • pnpm --dir docs build and git diff --check pass.
  • Chromium renders a JPEG at 320×213 and a genuine HEIC at 240×160 through the built endpoint and a local test image service. Both requests return 302 with replacement versions retained, followed by WebP images at the requested widths. The HEIC decoder in this harness is macOS sips; this is not a hosted-provider or production-deployment claim.
  • Admin English/Arabic verification was blocked by an Astro compile-metadata error in the isolated fixture; the screenshot below is the minimal page exercising the actual image endpoint.

JPEG and HEIC files rendered as resized WebP images through EmDash's image endpoint in a local test fixture

@changeset-bot

changeset-bot Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 024660b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/plugin-test Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
create-emdash Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@2175

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@2175

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@2175

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@2175

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@2175

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@2175

emdash

npm i https://pkg.pr.new/emdash@2175

create-emdash

npm i https://pkg.pr.new/create-emdash@2175

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@2175

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@2175

@emdash-cms/plugin-test

npm i https://pkg.pr.new/@emdash-cms/plugin-test@2175

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@2175

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@2175

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@2175

@emdash-cms/registry-loader

npm i https://pkg.pr.new/@emdash-cms/registry-loader@2175

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@2175

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@2175

upgrade-emdash

npm i https://pkg.pr.new/upgrade-emdash@2175

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@2175

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@2175

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@2175

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@2175

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@2175

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@2175

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@2175

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@2175

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@2175

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@2175

commit: 024660b

@masonjames
masonjames marked this pull request as ready for review July 21, 2026 13:58
@github-actions github-actions Bot added the review/needs-review No maintainer or bot review yet label Jul 21, 2026

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a sensible, well-scoped bug fix: HEIC/HEIF files are undisplayable in browsers, so converting them client-side before they hit the existing local-media upload flow is the right layer to solve it. The change is additive (no break), the CSP-compatible heic-to/csp import is appropriate, the changeset is user-facing, and no user-visible strings were added. Tests cover conversion behavior, browser renderability, and end-to-end flow through the media API.

I read the changed files and traced the two call-sites (MediaLibrary and MediaPickerModal). The only meaningful gap is that the same HEIC fix is not applied to uploadToProvider, so external-provider uploads can still store an undisplayable original. The rest of the code looks solid.

Comment thread packages/admin/src/lib/api/media.ts Resolved
Comment thread packages/admin/src/lib/media-upload.ts Resolved
@github-actions github-actions Bot added review/needs-rereview New commits since the last review size/L cla: signed and removed review/needs-review No maintainer or bot review yet size/M labels Jul 21, 2026
@ascorbic

Copy link
Copy Markdown
Member

I'm a bit reluctant to add a big new WASM dependency for this. It seems like something the image server should be handling.

@masonjames masonjames changed the title fix(admin): convert HEIC uploads for browser display fix: delegate HEIC media to configured image services Jul 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

@github-actions

Copy link
Copy Markdown
Contributor

This PR has been inactive for 14 days. It will be closed automatically in 7 days if there is no further activity.

If you're still working on this, please push an update or leave a comment.

@github-actions github-actions Bot added stale and removed stale labels Aug 13, 2026
@github-actions github-actions Bot mentioned this pull request Aug 24, 2026
11 of 18 tasks
@github-actions github-actions Bot added stale and removed stale labels Aug 28, 2026
@masonjames

Copy link
Copy Markdown
Contributor Author

Refreshed onto current main (7f20c8327) in 8783bc82c.

Local validation is clean: full build, 64 focused core media tests, 10 admin thumbnail tests, package typecheck, zero-diagnostic type-aware lint, formatting, and git diff --check. The prior red Browser Tests job was an unrelated editor-toolbar focus assertion (1 failure among 2,459 tests); the current-main refresh has queued a fresh CI run.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

This PR is waiting on its author because it has merge conflicts with main, and it has had no activity for 14 days. It will be closed in 7 days unless there is activity: push an update or leave a comment to keep it open.

@github-actions github-actions Bot added the stale label Oct 9, 2026
Avoid sending stored-media requests to Astro’s local-only image endpoint when an external service is configured. Preserve public source versions and mutable cache headers while leaving local transforms and upload acceptance unchanged.
@masonjames
masonjames force-pushed the codex/heic-media-support branch from 8783bc8 to 024660b Compare October 9, 2026 15:04
@masonjames masonjames changed the title fix: delegate HEIC media to configured image services fix(core): use external image services for stored thumbnails Oct 9, 2026
@github-actions github-actions Bot removed the stale label Oct 9, 2026

@danielmlr danielmlr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is a good fix, and it's great that the image service does the work now! It needs two small changes before we can merge it.

  • Please only send the new redirect when someone is signed in (ctx.locals.user), and change its Cache-Control from public to private. Only the admin uses these /_image links, and the admin is always signed in. Right now, though, anyone can ask for a link to any file name at any size. On an image service that charges for each new image, a stranger could run up the site owner's bill this way, and on a service that protects its links with a signature, anyone could get a valid one. With private, a shared cache can't pass a signed-in user's redirect on to someone else. Visitors who aren't signed in won't notice any difference.
  • Please rewrite the changeset in plain words and say that the fix needs a storage publicUrl. People read it in the changelog when they upgrade, so it should tell them whether the fix applies to their site. For example: "Fixes media library thumbnails on Node sites that use an external Astro image service and a storage publicUrl. The image service now makes the thumbnails, including HEIC if it supports it, so the admin no longer loads the full original."

Thanks again!

@emdashbot emdashbot Bot added review/needs-review No maintainer or bot review yet and removed review/needs-review No maintainer or bot review yet labels Oct 20, 2026
@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond and removed review/needs-review No maintainer or bot review yet labels Oct 20, 2026
@danielmlr danielmlr self-assigned this Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants