Images are usually where a CMS loses its order: 400 files in the root, no source, no alt text, and nobody dares to delete anything. RustyCMS gives every asset a folder with defaults, an editorial record and an index that knows where it is used.
Folders that carry their defaults
A folder can hold default values for tags, license and credit. Every upload into it picks them up — but only where the image itself brings nothing; explicit values stay untouched.
PUT /api/assets/folders/blog/meta
{
"description": "Blog hero images",
"defaultTags": ["blog", "hero"],
"defaultLicense": "CC-BY-4.0",
"defaultCredit": "Editorial team"
}
The record on the image
Every asset has a sidecar with derived data (dimensions, hash, blurhash) and editorial fields: title, credit, license, default alt text, tags. The alt text on the asset applies wherever the field in the entry does not override it — maintain it once, correct everywhere. The list filters by folder, MIME type, minimum size, transparency, tags and unused=true — only assets without a single reference, for the cleanup round.
Three ways in, small on arrival
Upload via multipart, from a URL, or as base64 — the last one for tools that cannot touch a file. Optionally every upload runs through an optimization pass: longest edge down to 2560 pixels, re-encoded as WebP. A 10 MB phone photo becomes roughly 400 KB before it hits the disk, the backup or the rsync. It is opt-in (RUSTYCMS_ASSET_AUTO_OPTIMIZE), SVG and GIF are never touched, and a result larger than the original is discarded. The original can be archived on request.
From the phone straight into the CMS
An upload ticket is a short link — /u/<id> — that lets exactly one image into exactly one predetermined folder, for a few minutes, without a login. The page behind it has a camera button. Desktop to phone, take the photo, done. It is also the path for AI assistants: a model cannot pass an image on as bytes, but it can mint a ticket over MCP, hand over the link and poll the folder afterwards.
Rename without fear
A rename or a move to another folder rewrites every entry that references the image in the background — no re-save in the editorial team. A referrer index keyed by content rather than path makes that possible. The same index answers ?usages=true: which entries, which field, which language.
What doesn’t happen
Folders are one level deep, not a tree. Filenames are lowercased and sanitized, and a second upload to the same path is rejected instead of silently overwritten. No cloud storage as a prerequisite — assets live in the content directory.