Media management
Foundry preserves authored media in its collection roots. Metadata lives beside
an original as <filename>.meta.yaml. Responsive output is derived build data,
not a replacement for the original.
Responsive images and deterministic optimization
Add this to your site configuration to opt in:
media:
responsive_images: true
widths: [320, 640, 960, 1280]
jpeg_quality: 82
require_alt: false
Run foundry build or foundry assets build to generate variants. You can also
run foundry media optimize, which refreshes the public assets and variants
without rendering pages. Omitted widths and quality use the values above.
Widths are sorted and deduplicated; upscaling is never performed. Configuration
accepts at most 16 widths from 1 through 8192 and JPEG quality from 1 through 100.
JPEG and static PNG files in enabled copied collections receive proportional variants. JPEG pixels are oriented using EXIF before resizing; generated files strip EXIF, including location data. PNG transparency is retained. At full size, Foundry keeps the original URL when re-encoding would increase its size. Animated GIF/PNG, WebP, AVIF and SVG are preserved and receive no automatic transforms. Transforms reject images over 32 MiB or 40 megapixels before full decoding.
Generated files live under public/_foundry/media/. Names include a digest of
source bytes, transform size, quality and pipeline version. Identical inputs and
settings produce identical bytes and URLs with the same Go/library versions.
Replacing a source changes its variant names. Source files and sidecars are never
rewritten by optimization. The JSON index and variants are published with the
static site and served by Foundry at /_foundry/media/.
Rendered local <img> tags receive srcset, a default sizes="100vw", and
intrinsic width/height when neither dimension is already specified. Existing
srcset, sizes and dimensions win. Theme authors should supply a sizes value
that describes their actual layout. Remote images are not downloaded or changed.
Regenerate public output after replacing or trashing source media; old public
copies remain accessible until that output is rebuilt. A clean foundry build
removes stale derived files; incremental asset builds retain older variants.
Accessible image metadata
Use meaningful inline alt text in Markdown:

You can also edit Alt Text in the admin media details form or save a sidecar:
alt: A green tree beside the entrance
Saved metadata fills missing or empty inline alt text when rendering local media. Nonempty inline descriptions take precedence. For intentionally decorative images, select Decorative image (empty alt text) in the admin form, or set:
decorative: true
This produces empty alt text and role="presentation" when no meaningful inline
alt is supplied. Hand-authored decorative HTML can use alt="" with
role="presentation", role="none", or aria-hidden="true".
Set media.require_alt: true to reject rendered images without a description or
an explicit decorative declaration, and reject image metadata saves lacking
both. foundry validate checks Markdown image accessibility using the same
metadata rules. Final rendered output is checked too, including template/plugin
images. Uploads remain possible before metadata is completed. Existing bulk tag
editing remains available and preserves the decorative and technical metadata.
Preview orphan cleanup and recover changes
The admin Media page has a Media Audit panel. Its preview reports Markdown accessibility issues and potential orphan references without changing files. The same report is available from the CLI:
foundry media audit
foundry media audit --json
The scanner checks current content (including drafts), project data, effective
configuration, active theme sources and plugin sources for media: references
and public URLs. It handles escaped URLs and considers references in frontmatter,
HTML, CSS and JSON. Sidecars, retained versions and trash are excluded as assets;
references that exist only in historical content do not protect current assets.
CSS files under the configured content assets' css/ directory are also recorded
as used because they contribute to the automatically generated CSS bundle, even
when no source file references their individual URLs.
Potential orphan does not mean safe to delete. Dynamic URL construction, external consumers and references outside the scanned roots may be invisible. Inspect each candidate and its usage before choosing an action. The admin's existing Delete action moves an individual file and its sidecar to Trash, and Restore recovers them. No bulk or automatic orphan deletion is added.
The CLI also supports a preview followed by explicit recoverable trash:
foundry media trash media:images/unused.jpg
foundry media trash media:images/unused.jpg --apply
The apply command runs a fresh audit and refuses references that are known to be used or absent from the candidate list. It moves the original and metadata to the existing lifecycle Trash instead of permanently deleting them, then prints the restore command for the retained path:
foundry media restore content/images/unused.trash.20261001T120000Z.jpg
foundry build
Use the actual retained path printed by the command. Restore also recovers the sidecar. If a current file exists, the existing versioning workflow preserves it before restoring. Rebuild after trash/restore to update published output.
Admin API
GET /__admin/api/media/audit (or your configured admin prefix) requires
media.read and returns assets, potential_orphans, accessibility, and
notes. It performs no writes. sdk/admin/media.js exposes it as media.audit().
The existing metadata API accepts metadata.decorative alongside metadata.alt.
It requires media.write, retains technical fields such as the content digest,
and uses existing metadata version history. Lifecycle actions retain their
existing media.lifecycle capability requirements.
