Skip to content
Content

Media

Upload an image once and use it anywhere. Lettern serves it in the right size and format for every screen.

On this page

The media library holds every image, video and document on your site. Upload a photo once, use it on any page, and Lettern makes the smaller, faster versions each visitor's screen needs.

#Upload files

Open Media in the sidebar and press Upload. You can also upload right from an image field or an Image block, while you pick a file.

Every upload is checked before it's kept:

  • The real file type is read from the file itself, not its name.
  • SVG images are cleaned of scripts.
  • Location and camera details are removed from JPEG photos.
  • Uploading the same file twice to the same folder gives you the one you already have.

#Describe each image

Click a file to open it. Fill in its Alt Text: a short description of what the image shows, for people using screen readers and for search engines. The SEO checks tell you when a page has images without it.

You can also give the file a clearer Name, a Caption and a Folder, then press Save.

#Keep the important part in view

When you open an image, click the spot that matters most, like a face or a plate. That's the focal point: whenever the image is cropped, for a square card or a wide banner, that spot stays in frame.

#Find and organize

Put files in folders by typing a folder name when you open them, like team/2026. Then narrow the library down:

  • Search by name or alt text.
  • Filter by Kind: images, videos, audio, PDFs or other files.
  • Pick a Folder.

Switch between a grid and a table, and choose what to show and how to sort under Display. To find images without a description, show the Alt Text column: it marks each image Added or No alt text. Your view follows you on every device, and the media pickers work the same way.

Select several files to delete them at once. Lettern won't delete a file that's still used on your site, and tells you where it's used.

#Show images on your pages

Add an Image block and pick an image. Lettern writes the whole responsive image for you, with its width and height set, so the page never jumps while it loads. Two settings under Advanced, in the Content tab, help it load fast:

  • Load First: turn it on for the main image at the top of a page.
  • Shown Width: how wide the image is shown, so the browser picks the right version, e.g. (min-width: 64rem) 50vw, 100vw. Empty means the full width.

An image can also be a background: select a block and pick one under Design → Fill → Image.

#Settings

The Settings tab of Media (also under Settings → Media) sets the Max Upload Size in MB, with your server's own limit under it, the Image Quality (40 to 95), whether to Serve AVIF Images (smaller than WebP, slower to make) and whether to Remove Photo Metadata (location and camera details). The last two are on unless you turn them off.

#For developers

#Responsive images

Lettern makes WebP and AVIF versions of each image in several widths (480, 960, 1440 and 1920 pixels where the original is wider, plus the original width up to 2560) the first time they're requested, and keeps them in public/_cms/img/, so static pages load them without PHP. AVIF needs GD built with AVIF support, or Imagick. Variant URLs carry a version that changes with the pixels and the focal point, so a replaced image never shows from a cache.

The Image block renders a complete <picture> element. A background image is stored as media:<id>; you can also bind style:backgroundImage to an image field. To show a field's image, bind the Image block's image to it:

JSON
{ "type": "image", "bind": { "image": "entry.hero" } }

In PHP, a media field's value renders itself ((string) $entry->hero), and offers img(['sizes' => …, 'priority' => true]) and src(1200, 'jpg').

#Importing from a URL

media/import accepts a public URL or base64 data. Downloads can't reach private network addresses, are size-limited and are checked like any upload.

#Media in git

Every item has a small record in content/media/<id>.yaml, written whenever you upload, change or delete a file. The files themselves live in public/media/. Commit both, and a fresh clone, a reset or a deploy has every image with the same id, alt text and focal point: the media table is an index Lettern rebuilds from these files.

YAML
id: 01m5x9jmrth1ggeatmbzxcz7vk   # lowercase ULID, equals the file name
path: media/2026/10/editor-k3j2.png
name: Editor
folder: screens
alt: The entry editor with a page open
focal: { x: 50, y: 50 }

Only id and path are required: type, size, hash and dimensions are read from the file. A record is held to the same bar as an upload, so one pointing outside public/media, at a file of the wrong type or at an SVG with scripts is refused. If a record won't parse, nothing is deleted until it's fixed.

Lettern picks up changes on php cms sync, at install, before a full build, after any admin request, and when a page asks for an id it doesn't know. Remove a record and the item goes on the next import; the file stays until you delete it.

A /media/… URL in an image field gets the same responsive <picture> as an id once the file has a record, so a tool that writes files to a fixed path only has to add one.

#Checking for problems

php cms media:check imports the records and lists ids and /media/ URLs that point at nothing, records without a file, files without a record, and items nothing uses. --strict exits with an error when something is broken, --json prints the report (the media/report ability gives the same), and --adopt turns files without a record into media items.

php cms build warns about every image a page asks for that isn't there, and --strict makes those fatal. media/delete refuses a file that's still in use and says where; pass force to delete it anyway.