Browse the documentation

Guides

Manage images and files

Upload, find and reuse images, documents and fonts.

Every photograph, logo, PDF and web font a site uses is one file in the media library, uploaded once and reused wherever you need it. This page covers uploading, finding a file again, describing it, how an image reaches a visitor's browser, where the bytes live, and what deleting one does.

You need the content.view permission to open the library, and content.manage to upload, edit, optimise or delete. On an install with workspaces, each workspace sees only its own files; see workspaces.

Upload a file

  1. Open Media in the sidebar.
  2. Press the plus button beside the Media Library heading. The Upload media dialog opens.
  3. Drop files on the left-hand area, or click it to browse. Each file appears as a thumbnail on the right, and the cross on a thumbnail takes it out again.
  4. Press Upload. Files go up one at a time and the dialog closes when the last one finishes. A file that fails is counted in a notification; the others still upload.

Files uploaded here are stored as public, so the theme can serve them to a visitor who has no session.

What Thallo accepts

config/uploads.php decides. allowed_types ships as image/*, video/*, audio/*, application/pdf and font/woff2. The type is read from the file's own bytes, not from its name and not from what the browser claims, and anything outside the list is refused.

max_size caps one file at 10 MB. UPLOADS_MAX_SIZE in .env changes it, in bytes.

The first 64 KB of every upload is also scanned: a file containing <?php, <?= or <script is refused, which rules out an SVG that carries script.

Find a file again

The list is newest first, thirty files to a page, with the count and a pager at the bottom. The search box matches the file's name, in any case, and takes % and _ as the characters they are. The buttons above it — All, Images, Videos, Audio and Docs — narrow by type. Docs means everything that is not an image, a video, audio or a font, so a typeface uploaded from Site › Appearance shows up only under All.

Describe a file

Select a file to open its preview and, beside it, its panel. An image preview has Full and Thumbnail tabs; Thumbnail is the 160-pixel-wide variant the list uses.

  • Title renames the file in the library. It is what the search box matches.
  • Alt text and Caption are free text.
  • Tags takes one tag at a time: type it and press Enter, click a tag to remove it.
  • File URL is the address the file is served at, with a copy button. A private file shows a Signed link instead: it works without signing in, and stops working when it expires (uploads.signed_urls.ttl, an hour by default).

Save changes writes all four at once.

The alt text and caption follow the file onto pages: an Image block whose own alt or caption is empty uses the file's, and a block's own always wins. A template can read them with media_text(). Tags stay in the library. The content API returns an asset field as the file's uuid only, so a headless front end does not receive them.

Put a file into content

An entry field of type asset takes one: drop a file on it to upload, or press Choose from library. Either opens Add media, which has an Upload tab and a Media library tab.

In the Design view, the Image block's image field uses the same picker. Fill in alt with what a screen reader should say, and caption to print a line under the picture; left empty, each falls back to the file's own from the library. The Gallery block holds Image blocks and takes each one's alt the same way.

How an image reaches the page

A theme never writes a file path. Each image slot asks for the file by its id and for a list of widths; the default theme's Image block asks for 480, 768, 1024 and 1536. Back come the original at /v1/blobs/{uuid} and one candidate per width, /v1/blobs/{uuid}?width=768 768w, and the browser picks.

  • Only a public, undeleted file resolves at all. When nothing resolves the theme leaves the picture out rather than printing a broken one.
  • Only JPEG, PNG, GIF and WebP get candidates. An SVG is served as it is.
  • A width above max_width in config/uploads.php — 2048 — is dropped from the list.

The resize happens on the first request for that width and is cached for cache_ttl, seven days. Both the original and the variants answer with Cache-Control: public, max-age=86400, so a browser holds them for a day. Resizing needs a PHP image extension: IMAGE_DRIVER in .env is gd or imagick.

Make an image smaller

Optimize image re-encodes the file at the same dimensions and writes it back over the original. If the re-encode is no smaller, Thallo keeps the original bytes and says Already optimal.

Resized variants follow the new file at once: each one is keyed to the file's size and last change, so the next request for a thumbnail or a srcset width is made from the optimized original.

Where the files are stored

disk in config/uploads.php names a disk declared in config/storage.php, and UPLOADS_DISK in .env overrides it. The default is uploads: a local disk rooted at storage/uploads/.

Each file is stored under a generated name — the upload's Unix time, an underscore, sixteen hex characters, the original extension — so two uploads of logo.png never collide. The name you see in the admin is held in the database, not on the disk.

config/storage.php also declares an s3 disk for S3-compatible object storage, but only the local and memory drivers are built in. Pointing UPLOADS_DISK at s3 fails with Unsupported disk driver 's3'. Install it with: composer require glueful/storage-s3.

Nothing in storage/uploads/ is in the database, so it needs backing up alongside it: see back up and restore.

Delete a file

Press Delete, then Delete in the confirmation. The library stops listing the file, /v1/blobs/{uuid} answers 404, and there is no undo in the admin. The bytes stay on the disk for a grace period, 30 days by default (UPLOADS_PURGE_DELETED_AFTER_DAYS); then the scheduler's blob_purge job removes the file and its row for good. php glueful blobs:purge does it by hand. The deletion is recorded under Users & Access › Audit Log.

Before you delete, read the panel's Used in list. It names the entries whose drafts point at the file, through an asset field or a block inside one (an Image block in a page's body, say), with each one's status. Header, footer and settings images, such as the site logo, are not entries and are not listed. On a site upgraded from a release that did not count block images, run php glueful thallo:media:rebuild-usage once to fill the list in.

A page that used a deleted file still renders. The theme resolves the image first and skips the element when it cannot, so the picture goes and everything around it stays.

Show your location on a map

The Map block (Blocks tab, Media) shows a Google map. It needs no Google account or API key.

  1. Insert it where you want the map: a page, a post, a Contact section, or the footer under Site › Header & footer.
  2. Type your Address or place, as you would search for it in Google Maps: Accra Mall, Accra.
  3. Set Zoom (1 shows the world, 21 a single building; 15 is a few streets), View (map or satellite) and Height.
  4. Turn on Show a Get directions link to add a link that opens Google Maps with the route to your address.

For a pin on the exact spot, open your place in Google Maps, choose Share › Embed a map, and paste the link or the whole <iframe> code into Google Maps embed link. Thallo uses it only when it is Google's own embed link; anything else is ignored and the map comes from the address.

On the stage a click selects the map rather than panning it. On the published page it pans and zooms as usual.

A Google map sets Google's cookies as soon as it loads. If your site asks visitors for consent first, turn on Load the map only when clicked. The page then shows a placeholder saying the map comes from Google, with a Show map button and an Open in Google Maps link. Nothing of Google loads until the visitor presses the button.

Check it worked

  • The file appears at the top of the library, with its size and today's date.
  • Selecting it shows the right Type, Size and a Visibility of public.
  • The page you put it on shows the image to a logged-out visitor, and the page's source names the image /v1/blobs/… with a srcset of ?width= candidates.