Image optimization
The optional Corex Media add-on converts uploads to WebP and renders optimized images — without you
hand-writing <img> tags. The framework runs fully without it; it degrades gracefully everywhere.
WebP on upload
Section titled “WebP on upload”When the server supports GD/Imagick + WebP, uploading a JPEG/PNG generates a sibling .webp and preserves the
original. With no support, the upload succeeds unchanged — no error. SVG follows your site’s existing policy.
The
.webpsibling is written next to the original on disk, not registered as its own Media Library item — so it won’t show up as a separate attachment. Delivery happens through the<picture>helper / optimize filter below; a plain inserted<img>keeps using the original unless it’s rendered through the helper.
Settings
Section titled “Settings”Under Corex → Settings → Media you can toggle WebP conversion, set the quality (1–100, default 82), and toggle JPEG/PNG conversion independently. The panel shows a live server-support read-out — GD, Imagick, WebP encode, and uploads-directory writability (also in Tools → Site Health). The section is hidden until the add-on is installed and disabled until it’s active. Originals are always preserved — that is not a setting.
Filter seams (for code-level control): corex_media_webp_enabled, corex_media_webp_quality,
corex_media_convert_jpeg, corex_media_convert_png, corex_media_convertible_mimes.
The WebP activation gate
Section titled “The WebP activation gate”A .webp is not served just because it exists. After conversion, CoreX measures the derivative and serves it
only when it passes a gate; otherwise the original is delivered. The default gate:
- the derivative exists and is a valid image;
- its dimensions match the original;
- it is smaller than the original by at least the minimum saving threshold (default 5%, set under
Settings → Media or via the
corex_media_min_savingfilter).
The result is tracked per attachment (_corex_webp meta): original/generated paths + bytes, saving %, dimensions,
quality, source hash, generated-at, and active_for_delivery + inactive_reason. So a WebP that came out larger
(common for already-optimized PNGs) is generated but quietly not served — you always get the smaller file.
Regenerating existing uploads
Section titled “Regenerating existing uploads”To backfill WebP siblings for images uploaded before conversion was on:
wp corex media regenerate-webp --dry-run # preview what would convertwp corex media regenerate-webp --limit=50 # convert in batcheswp corex media regenerate-webp --attachment=123 # a single attachmentIt never deletes or overwrites originals, skips attachments that already have a .webp sibling, skips
unsupported types, respects the current settings, and reports convert/skipped/converted/failed counts. Run it on
local/staging first and back up before large runs.
Resetting / cleaning up
Section titled “Resetting / cleaning up”To remove CoreX-generated WebP derivatives safely:
wp corex media reset-webp --dry-run --all # previewwp corex media reset-webp --all # all tracked derivativeswp corex media reset-webp --attachment=123 # a single attachmentIt deletes only files tracked in a _corex_webp record — never originals, never manually-uploaded WebP, never
any untracked file — clears the record afterwards, and reports scanned/deleted/skipped/failed counts. Deleting a
WordPress attachment also removes just its tracked CoreX derivative automatically.
Generated WebP files are not separate Media Library attachments — the library shows one original per upload. WebP status/actions surface through Settings → Media (a full attachment-detail UI is future).
The picture helper
Section titled “The picture helper”echo $media->render( $attachmentId, 'large' ); // lazy, async, webp + fallbackecho $media->render( $heroId, 'full', true ); // LCP: fetchpriority=high, eagerIt emits an accessible <picture>: a WebP <source> + an <img> fallback with the real alt,
loading="lazy" + decoding="async" by default, a responsive srcset/sizes, and — for a designated LCP/hero
image — fetchpriority="high" and eager (not lazy). With no WebP sibling it degrades to a plain optimized <img>.
For a raw image URL (e.g. a block attribute), use $media->pictureForUrl( $url, $alt, $lcp ). Any block can
opt into optimized output without depending on the add-on through the filter seam:
$img = sprintf( '<img src="%s" alt="%s" loading="lazy" />', esc_url( $url ), esc_attr( $alt ) );echo apply_filters( 'corex_media_optimize_image', $img, [ 'url' => $url, 'alt' => $alt ] );When Corex Media is active and a gated WebP sibling exists, the filter returns the <picture>; otherwise it returns
your fallback <img> unchanged. Pass class (and optionally loading/lcp) in the args so the wrapped <img>
keeps its markup. The built-in CoreX UI image blocks (Hero, Gallery, Team) already opt in through this seam — and
their styles set picture { display: contents } so the optional wrapper never changes layout.
Diagnostics
Section titled “Diagnostics”Site Health and wp corex doctor report GD/Imagick/WebP/AVIF support as advisory status — so a missing capability
is visible, never a hard failure.
Out of scope
Section titled “Out of scope”AVIF generation and CDN/Blob offload are a later increment (the probe still reports AVIF support). This feature augments WordPress’s own image handling — it does not replace it.