Humble.Umbraco.MediaExtensions
18.0.4
Prefix Reserved
dotnet add package Humble.Umbraco.MediaExtensions --version 18.0.4
NuGet\Install-Package Humble.Umbraco.MediaExtensions -Version 18.0.4
<PackageReference Include="Humble.Umbraco.MediaExtensions" Version="18.0.4" />
<PackageVersion Include="Humble.Umbraco.MediaExtensions" Version="18.0.4" />
<PackageReference Include="Humble.Umbraco.MediaExtensions" />
paket add Humble.Umbraco.MediaExtensions --version 18.0.4
#r "nuget: Humble.Umbraco.MediaExtensions, 18.0.4"
#:package Humble.Umbraco.MediaExtensions@18.0.4
#addin nuget:?package=Humble.Umbraco.MediaExtensions&version=18.0.4
#tool nuget:?package=Humble.Umbraco.MediaExtensions&version=18.0.4
Humble Media Extensions for Umbraco
Smaller images out, sensible images in.
Two jobs, both automatic:
- Delivers optimised assets. Visitors receive AVIF or WebP instead of your JPEGs and PNGs, chosen from what their browser actually supports. Same URLs, same media library, same templates — the images just get smaller.
- Keeps uploads sane. A 6000px photo straight off a phone is bigger than any page needs, so oversized uploads are resized once on save. The stored original stays a sensible size instead of becoming a permanent tax on every crop.
That's the scope. Editors keep working exactly as they do now, and pages get lighter.
When you want art direction, the package also ships an opt-in Picture property editor (see Picture property editor).
Install
dotnet add package Humble.Umbraco.MediaExtensions
On boot, HumbleImageSharpComposer wires everything up. No startup code, no template changes.
Optionally, add a Magick.NET runtime to enable AVIF:
dotnet add package Magick.NET-Q8-AnyCPU --version 14.15.0
Version 14.15.0 or a newer compatible 14.x release. Other quantum-depth and platform-specific Magick.NET packages are
not currently supported.
Skip it and everything still works. Without Magick.NET there is no AVIF encoder, so delivery falls back to WebP —
which ImageSharp handles natively and which every current browser reads. Upload resizing is unaffected. Nothing throws,
and the build does not fail; it prints one informational line telling you AVIF is off. Set
HumbleSuppressMagickNetHint=true to silence it.
Configure
Everything is optional — the defaults below are what most sites want. Settings live under
Humble:Umbraco:MediaExtensions.
// appsettings.json
{
"Humble": {
"Umbraco": {
"MediaExtensions": {
"AutoFormat": true, // serve a better format when the browser takes one (default)
"Formats": [ "avif", "webp" ], // preference order, best first
"NegotiateWildcardAccept": true, // */* or a missing Accept still gets the better format (default)
"Quality": 75, // delivery encode quality (uploads always use max quality)
"Resize": { // cap upload dimensions (on by default)
"Enabled": true,
"MaxWidth": 4000, // optional; omit to follow Umbraco's Imaging:Resize
"MaxHeight": 4000 // optional; omit to follow Umbraco's Imaging:Resize
}
}
}
}
}
Or via environment variables (double underscores, one index per array entry):
Humble__Umbraco__MediaExtensions__AutoFormat=false
Humble__Umbraco__MediaExtensions__Formats__0=avif
Humble__Umbraco__MediaExtensions__Formats__1=webp
Humble__Umbraco__MediaExtensions__NegotiateWildcardAccept=false
Humble__Umbraco__MediaExtensions__Quality=75
Humble__Umbraco__MediaExtensions__Resize__Enabled=false
Humble__Umbraco__MediaExtensions__Resize__MaxWidth=4000
Humble__Umbraco__MediaExtensions__Resize__MaxHeight=4000
Delivery — for each media image (.jpg, .jpeg, .png, .gif under your Umbraco media root — /media by
default, and a custom Umbraco:CMS:Global:UmbracoMediaPath is picked up automatically), the entries in Formats are
tried in
order; the first one the browser accepts and that has a working encoder wins. If none match, the original is served
unchanged. AVIF only wins when a Magick.NET build that can write it is installed — otherwise it falls through to WebP on
its own. Requests that already carry ?format= are left alone, and HMAC-signed media URLs are re-signed so they keep
validating. Every negotiated response carries Vary: Accept so shared caches keep the per-format variants apart. Set
AutoFormat to false to always serve the original. Served images are encoded at Quality (1-99, default 75);
that setting is delivery-only and does not change files stored in the media library.
By default (NegotiateWildcardAccept: true), a request whose Accept is a wildcard (*/*, image/*) or missing
entirely is treated as accepting the better format. That is what curl, a bare fetch(), and most non-browser clients
send; real browsers are unaffected either way, since they always send an explicit image/avif/image/webp. Set it to
false only if some client in your setup asks for anything and then cannot handle what it gets.
Upload resizing — on by default. Any image larger than the limit is resized down to fit as it is saved, keeping its
proportions and its original format (a JPEG stays JPEG, a PNG stays PNG, a WebP stays WebP); the stored file and its
width/height/size properties are updated together, and smaller images are left alone. The limit follows Umbraco's own
Imaging:Resize setting — the largest size an image can be served at, so there is no point storing anything bigger.
Override per dimension with Resize:MaxWidth/MaxHeight, or set Resize:Enabled to false to store uploads exactly
as received. When a resize does happen, the image is re-encoded at maximum quality (100, or lossless for formats
such as PNG and GIF that have no quality knob). Quality above is for delivery only and is never applied to uploads.
A format we cannot write (HEIC/HEIF) is left untouched rather than rewritten into another format. Resizing never fails
a save — if anything goes wrong the upload is stored exactly as it arrived and the problem is logged.
Two ways to deliver AVIF/WebP
Behind Cloudflare or any other edge cache, put the format in the URL. Automatic negotiation is only safe when nothing caches between the browser and your site.
Recommended: format in the URL (<picture>), safe on every CDN
Each format gets its own URL (?format=avif), so every CDN, including Cloudflare's free plan, caches each variant
separately and keeps serving it from the edge. The browser picks the first format it supports via <source type>.
In a razor view, use the tag helper (add @addTagHelper *, Humble.Umbraco.MediaExtensions to _ViewImports.cshtml):
<humble-picture value="@Model.Photo" crop="hero" width="1200" quality="70" alt="A dog" loading="eager" />
or the HTML helper:
@Html.HumblePicture(Model.Photo, cropAlias: "hero", width: 1200, quality: 70, alt: "A dog", lazy: false)
Both produce:
<picture>
<source srcset="/media/x/dog.jpg?width=1200&quality=70&format=avif" type="image/avif">
<source srcset="/media/x/dog.jpg?width=1200&quality=70&format=webp" type="image/webp">
<img src="/media/x/dog.jpg?width=1200&quality=70" alt="A dog" width="1200" loading="eager">
</picture>
- One
<source>per configuredFormatsentry your install can actually encode, in preference order (an install without Magick.NET advertises only WebP). - Crop, width, and quality compose through Umbraco's
GetCropUrl. - The default is lazy loading. Use
loading="eager"(lazy: false) for an above-the-fold / hero image; lazy-loading your LCP image hurts Largest Contentful Paint. - Both accept
MediaWithCropsandIPublishedContent;<humble-picture>also accepts Picture editor values. - CSS backgrounds and URLs you build by hand need
format=added yourself.
Automatic negotiation: only without an edge cache
Any image URL without format= is negotiated from the request's Accept header, with zero template changes. The
response carries Vary: Accept so a cache that honors it keeps each format separate. Use it for sites served
straight from the origin, or behind a CDN that varies on Accept.
⚠️ Cloudflare mis-serves negotiated formats. Cloudflare's cache, on every plan, ignores
Vary: Accept. The first visitor's format gets cached under the plain URL and served to everyone: an AVIF a browser without AVIF cannot render, or a JPEG that never upgrades. On Pro and up, Cloudflare's "Vary for Images" fixes it: create a variants rule through Cloudflare's API that maps your image extensions (.jpg,.png, ...) toimage/avifandimage/webp. Umbraco's/media/.../photo.jpgURLs carry the extension it needs. On the free plan, use the format-in-URL approach above.
Headless / Delivery API: there is no razor helper — request the format directly, e.g.
/media/x/dog.jpg?width=1200&format=avif. That raw?format=URL is the headless recipe.
Picture property editor
An opt-in data type for art-directed, responsive images: one main image, cut to a named crop per breakpoint, with an optional replacement image for any crop.
- Settings > Data Types > Create, and pick Picture (group Humble).
- Treatments — the crops, each a name and a size in pixels.
- Breakpoints — the screen widths the picture changes at, and which treatment shows from each width up.
The value converts to PictureValue (Humble.Umbraco.MediaExtensions.Picture). Render it with the tag helper, after
registering it once in _ViewImports.cshtml:
@addTagHelper *, Humble.Umbraco.MediaExtensions
<humble-picture value="@Model.Hero" alt="" loading="eager" class="hero" />
- One
<source media>per breakpoint crop, widest first; the smallest-screen crop is the<img>. - When licensed, each crop is also offered as AVIF/WebP (format-in-URL sources), checked per crop — a crop can use a different image.
altdefaults to the media name (pass""for a decorative image);loadingdefaults tolazy;img-classsets a class on the<img>. Other attributes (class,slot, ...) stay on the<picture>.- Self-closing or with an end tag.
valuealso takes an ordinary media item (MediaWithCropsorIPublishedContent), with the same options asHtml.HumblePicture:<humble-picture value="@Model.Photo" crop="hero" width="1200" quality="70" alt="A dog" />.- The Delivery API returns the main image, the overrides and the treatments.
- Licensing: the editor is always registered, so stored values are never at risk. Without a Media Extensions
(or suite) license it is read-only: existing images still show and render, but can't be edited. The rendered
breakpoint
<source>s are free; the AVIF/WebP sources need a license.
A note on HEIC and HEIF
If a Magick.NET runtime is installed, Media Extensions can also read HEIC and HEIF, so an iPhone photo that lands in your media library still gets dimensions, crops, and resizing like any other image rather than breaking the pipeline.
They are never delivered: no browser renders HEIC or HEIF, so serving one would show a broken image rather than save anyone bandwidth. Delivery is AVIF and WebP.
For how the AVIF bridge works, using the package without Umbraco, and how it is built and packaged, see TECHNICAL.md.
Trademark
Not affiliated with, endorsed by, or sponsored by Umbraco A/S. Umbraco is a trademark of Umbraco A/S.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Humble.Umbraco.Common (>= 18.0.4)
- Humble.Umbraco.License (>= 18.0.4)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Humble.Umbraco.MediaExtensions:
| Package | Downloads |
|---|---|
|
Humble.Umbraco
Installs the complete Humble Starter Kit for Umbraco in one step. This package contains no code of its own — it is a shortcut that pulls in every published Humble package. Not affiliated with, endorsed by, or sponsored by Umbraco A/S. Umbraco is a trademark of Umbraco A/S. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 18.0.4 | 93 | 10/16/2026 |
| 18.0.4-rc.1 | 62 | 10/8/2026 |
| 18.0.3 | 100 | 10/7/2026 |
| 18.0.2 | 115 | 10/5/2026 |
| 17.0.4 | 93 | 10/16/2026 |
| 17.0.4-rc.1 | 58 | 10/8/2026 |
| 17.0.3 | 96 | 10/7/2026 |
| 17.0.2 | 97 | 10/5/2026 |