tspedtsberg
(Tobias Spedtsberg)
August 28, 2026, 7:41am
1
Hi
I want to discus the best solution for the goal of “never write an alt text again”.
For now I made a solution combining Umbraco.automate, Umbraco.AI and a custom “GetMediaPropertyAction” for Umbraco.automate. Since umbraco.automate doesnt ship with a “getmediaproperty” similar to their “getcontentproperty” action?
For now I have configured an automation flow with the following steps:
Trigger: Media Saved
Step 1: Get media property (custom action)
Getting the property of the media → altText
Step 2: Conditional If statement → Is the the altText property empty?
Step 3: Run AI agent
Running a low cost agent (haiku) with the prompt:
Write concise, descriptive alt text in under 125 characters for the following image: ${ trigger.mediaKey } Return only result
Step 4: Update Media Property
Requirements:
Umbraco.AI
Umbraco.automate
Ideas for similar other automations:
Seo texts
Can anyone confirm that umbraco.automate doesn’t ship with a “GetMediaProperty” action?
mistyn8
(Mike Chambers)
August 28, 2026, 9:04am
2
Ah for starters.. but that’s just the minimum.. as the alt text needs to describe the purpose of the image in the context of the surrounding content (or indeed if it’s been cropped to change the intent).
(also don’t forget images added via the rte, which already have a contextual alttext and caption you can use)
Five golden rules for compliant alt text | AbilityNet
Discord thread
Discord is great for playing games and chilling with friends, or even building a worldwide community. Customize your own space to talk, play, and hang out.
or if not on discord
https://discord-chats.umbraco.com/t/33245649/alt-text-support-in-umbraco
and a pr from @MikeMasey for discussion…
main ← MMasey:v17/improvement/media-picker-improvements
opened 11:42AM - 27 Jun 26 UTC
# Media Picker: alternative text support + accessible crop editing
## What th… is does
Adds **alternative text** support to the Media Picker with Crops property editor, and significantly improves the **keyboard and screen-reader accessibility** of the crop and focal-point editors.
The work touches the data type configuration, the backoffice editor, the value converter, the Delivery API, and the crop editor's keyboard support.
Due to how much is in this update, i've also recored a video of me rambling through it for those that prefer that kind of communication.
Watch me talk through the update here - https://www.youtube.com/watch?v=zj7creSgqMk
If you would like to test this locally too, here's a copy of my test content and templates - [media-picker-share.zip](https://github.com/user-attachments/files/29407761/media-picker-share.zip)
Admin login details are:
Username: `[email protected] `
Password: `1234567890`
### Alternative text
- New **Alternative text** mode on the data type — a three-option setting:
- **Off** — for non-image content (PDFs, documents) where alt text doesn't apply.
- **Show alt text field** — prompts editors to describe the image.
- **Mark as decorative image** — for purely decorative images; renders `alt=""` (WCAG 1.1.1).
- New data types default to **Show alt text field**; existing data types keep their stored config and are unchanged on upgrade.
- **Per-crop alt text** (optional) — each crop can carry its own description, with the main field used as a fallback.
- **Culture-variant alt text** — even when the picker property is invariant, alt text can be authored per language. On non-default cultures, media/crop editing is locked (it's a shared property) while the alt text fields stay editable and are labelled with the culture (e.g. *Alternative text (da)*).
- Alt text flows through to the **Delivery API**: `altText` at the top level of the media object and per-crop `altText` on each entry in the `crops` array. Culture resolution is server-side and case-insensitive.
- New **Hide crop zoom control** option for a simpler editor UI.
- Editor quality-of-life: the crop editor **auto-opens on first pick** when alt text is enabled; a **"How to write alt text"** help link (WCAG H37 guidance); and a **skip link** to jump keyboard users straight to the alt text field.
### Accessibility
- Crop editor is now fully keyboard-operable: **arrow-key panning** (Shift for larger steps) plus on-screen **N/S/E/W directional buttons**, with discoverable hint text.
- Focus is managed on save (returns to the focal-point view) with a screen-reader announcement.
- The focal-point setter gets matching keyboard support and hint text (`aria-describedby`).
- **Accessible reordering** of picked media via Move Up / Move Down buttons, with an ARIA live region announcing each move.
- Various screen-reader fixes across the picker, including a regression fix from earlier accessibility work.
## Why the defaults are safe
`Alternative text` defaults to **Off** behaviour for existing data types (their stored config is untouched), so existing content renders exactly as before. The feature is opt-in per data type.
## Background & community context
Alt text in Umbraco has been an open, actively-debated topic for **several years**, with contributions from many people across both the community and Umbraco HQ. This PR delivers the parts of that collective wish-list that can be solved well today, without waiting on larger platform changes.
A recurring conclusion from those discussions — and the design this PR follows — is to store alt text **on the property value** rather than on the media item. That naturally supports per-crop and per-culture descriptions, keeps the text **contextual to where the image is used**, and sidesteps the media-library-variant work that has blocked the "alt on the media item" approach.
References:
- GitHub discussion [#13690 — "Add alt attribute by default in Image Media Type"](https://github.com/umbraco/Umbraco-CMS/discussions/13690) (open since 2020, `community/up-for-grabs`, many contributors over time).
- Recurring **"Alt Text Support in Umbraco"** conversations in the community Discord.
## Breaking-change avoidance
- `IApiMediaWithCrops.AltText` ships as a **default interface implementation** returning `null`, so external implementers are not broken.
- `MediaPickerWithCropsValueConverter` gained an `IVariationContextAccessor` dependency; the previous constructor is **obsolete** and delegates via `StaticServiceProvider` (scheduled for removal in Umbraco 20).
- Invariant properties with alt text enabled resolve per-request (`PropertyCacheLevel.None`) to stay culture-correct; all other media pickers cache exactly as before.
- `MediaWithCropsDto.Prune()` now preserves crops that carry alt text even when they have no custom coordinates.
## Tooling
- Adds the **WCAG Guidelines MCP server** and documents the available MCP servers (`playwright`, `umbraco-cms`, `wcag`) in `MCP.md`. These were used while building and verifying this accessibility work.
## Testing
- Unit and integration coverage for `MediaPickerWithCropsValueConverter` — alt text resolution, per-crop/per-culture handling, culture fallback, and cache-level selection.
## Future work / opportunities (not in this PR)
Several of these come directly out of the community discussions and are flagged so they're tracked rather than lost.
**Considered and intentionally left out:**
- **Mandatory alt text (validation)** — a config option to require alt text, ideally only enforced when an image is actually selected. Whether it can hook into mandatory-field validation depends on how it integrates with the validation service, and it may only be enforceable when the property is configured mandatory in the schema. This is the main remaining ATAG B.3.1.1 gap and is the most likely follow-up.
- **A "fallback" / default alt text on the media item** — already achievable natively today (add an alt text field to the media item type and wire it up). Deliberately *not* part of this work: alt text should be **contextual**, and leaning on a global fallback is an anti-pattern if the text isn't a good fit. It's easy to do already and may not even be wanted after this update. It's also worth noting the **media library doesn't currently support multilingual content**, a further blocker to a per-culture fallback on the media item itself.
- **AI-assisted alt text** — generating alt text (with an editor review step) has come up in the community. It shouldn't be a core dependency, but storing alt text on the property value should make this **much easier to handle with Umbraco.AI** (untested) — leaving the door open as an optional package on top.
- **RTE / TipTap media parity** — the RTE media embed has contextual alt text + caption but no crops; the picker now has crops + alt text. Bringing the two to parity is a larger follow-up.
**Accessibility follow-ups:**
- **Non-visual feedback for focal point / crop adjustment** — currently only the live-region position text. An audio cue would help, but we should get **real AT-user feedback** before building it.
- **Upstream `@umbraco-ui/uui` fix — selectable media cards not togglable with NVDA.** Not fixable in this repo: in uui `2.0.0-rc.2` the selectable card renders an interactive `<a id="open-part">` plus a nested `<uui-checkbox>`, and adding `role="checkbox"`/`aria-checked` to the host produces an invalid non-leaf checkbox, so NVDA's browse cursor lands on the inner link. *Upstream fix:* when selectable, make the host the only accessible control and key `SelectableMixin` off `e.key` (`' '`/`'Enter'`) rather than `e.code`. *In-repo fallback:* non-selectable card + explicit labelled checkbox in the actions slot (trade-off: loses whole-card click-to-select).
- **Focal-point setter directional buttons** — keyboard arrows work, but no on-screen N/S/E/W nudge buttons like the crop editor now has (parity gap).
- **Real assistive-technology user testing** of the `role="application"` + live-region patterns across NVDA / JAWS / VoiceOver.
- **Automated accessibility regression tests** (axe/Playwright) — only backend C# tests exist today.
**Housekeeping:**
- **Per-culture caching** — invariant properties with alt text resolve per-request (`PropertyCacheLevel.None`), giving up caching; a per-culture cache key would restore it.
- **Localization** — new strings were added to `en.ts` only and need translating.
---
I'm really looking forward to getting the conversation started again, hopfully with a potentially viable solution too. This has been a really fun to work on!
---
_This item has been added to our backlog AB#70433_
Luuk
(Luuk Peters (Proud Nerds))
August 28, 2026, 9:23am
3
I think alt-text should be in the core CMS, but it seems really hard to come up with a solution that works all the time. @mistyn8 says is correctly: an alt text should describe the image in context. So just slapping on an alt text on a media node doesn’t cut it.
I agree that it’s better than NO alt, but not by much. Media nodes are not culture variant, so you can’t have an alt text per language anyway.
So you would need to be able to set an alt at the media picker level I guess?
My point is, there is a reason there is no concensus yet, but don’t let that discourage you. I would love to see your solutions!
mistyn8
(Mike Chambers)
August 28, 2026, 9:32am
4
Annoyingly HQ keep reinventing the wheel.. and why there isn’t a getEntity, with a repository selection to match existing backoffice patterns.. or if not the same media actions as content I’m unsure?
(or for that matter bindings in Automate that are just ufm expressions )
but looks like it’s a simple task to take
using Microsoft.Extensions.Logging;
using Umbraco.Automate.Core.Cms;
using Umbraco.Automate.Core.Security;
using Umbraco.Automate.Extensions;
using UmbracoConstants = Umbraco.Cms.Core.Constants;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
namespace Umbraco.Automate.Core.Actions.BuiltIn;
/// <summary>
/// A built-in action that fetches a single property value from a published content
/// item and exposes it to downstream steps without materialising the whole node.
/// </summary>
[Action("umbracoAutomate.getContentProperty", "Get Content Property",
Description = "Fetches a single property value from a published content item.",
Group = "Content",
This file has been truncated. show original
and swap out IPublishedContentCache for IPublishedMediaCache ?
maybe contribute back into
Monorepo for community created Umbraco.Automate packages
or
Community extensions and integrations for Umbraco Automate
the automate package space is becoming very fractured very quickly but shows what a good addition this is with the uptake! (might be nice to have an addon tag so that the marketplace can filter package addons?)
tspedtsberg
(Tobias Spedtsberg)
August 28, 2026, 10:30am
5
It seems that the “getmediaproperty” action was added to the development of automate 2 days ago:
using Microsoft.Extensions.Logging;
using Umbraco.Automate.Core.Cms;
using Umbraco.Automate.Core.Security;
using Umbraco.Automate.Extensions;
using UmbracoConstants = Umbraco.Cms.Core.Constants;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
namespace Umbraco.Automate.Core.Actions.BuiltIn;
/// <summary>
/// A built-in action that fetches a single property value from a media item and exposes
/// it to downstream steps without materialising the whole item.
/// </summary>
[Action("umbracoAutomate.getMediaProperty", "Get Media Property",
Description = "Fetches a single property value from a media item.",
Group = "Media",
Icon = "icon-picture",
This file has been truncated. show original