media

File uploads for the CMS (this example has it enabled — the Articles form has a cover field). Bytes live on disk, metadata in a built-in media table; SQLite never stores blobs, so the database stays small and backup = database + the media folder.

keydefaultdescription
pathrequired: folder for uploaded files, created on start
url_prefix/mediapublic URL prefix; must not overlap static, /cms, /soe or routes
max_file_size5mper-file limit, a number or "5m" / "500k"; hard ceiling 100m
typespng, jpg, gif, webp, pdfallowed types — a subset of that list

The file type is detected from content, not from the name. The server reads the magic bytes, assigns the canonical extension (a JPEG is always .jpg) and rejects anything it cannot recognize — an .exe renamed to .jpg does not pass. Nothing client-supplied is stored: the file name is the record id, so /media/0/12.jpg. svg is not supported deliberately — it is XML that can carry scripts.

How it works day to day: add { "name": "cover", "widget": "file" } to a table's form_fields (the column is plain text — it stores the url). Picking a file uploads it immediately and puts the url into the field; the Media section in the admin lists everything uploaded (deleting is admin-only). Files are served with a forever-cache header (immutable) — content under an id never changes — plus X-Content-Type-Options: nosniff.

Uploads require sign-in (any role); files are sharded on disk 1000 per folder — the /media/0/ part of the url is that shard. Remove the block to disable the feature entirely: no table, no routes, no folder.

← All articles in this group