Skip to content

The image bank

/media. Browse, describe, tag, mark up and move the pictures the library and the question bank draw on.

Not moderator-only: anybody holding an image-library grant works here, scoped to the libraries they hold. readable_libraries returns None for a moderator — meaning every library — and a set of ids for everybody else.

The route itself is only behind sign-in; the scoping is what does the work, and the Images menu entry is drawn only for somebody whose GET /media/libraries comes back non-empty. A learner who typed the address would find an empty manager.

What a figure is, what an asset records, how the slideshow behaves and where the bytes live are in Figures. This page is the surface.

The view lives in the address

Which page, which library, what was searched. A link to page 3 of the radiology library opens on page 3 of the radiology library, and Back lands where you were.

Libraries

The rail down the side: All images with the bank's whole count, then one row per library with its own count. Choosing a library does not relabel "All images" with that library's count.

Act Who
Create a library moderator (POST /media/libraries) — names are unique, case-insensitively
Grant or revoke one moderator (POST/DELETE /media/libraries/{id}/grants)
Upload into one anybody who holds it
Move an asset between two anybody who holds both ends
Delete or restore an asset moderator

A library is created with user_id = None, like everything else in the bank.

Handing out a library grant is done on the Access page as well; both write the same media_library_grants row.

Uploading

POST /media/upload, multipart.

Rule Value
Images PNG, JPEG, GIF, WebP, SVG — up to 12 MB
Audio MP3, WAV, OGG, M4A, AAC — up to 60 MB. Heart sounds are the reason this exists: a murmur cannot be shown as a picture.
Video MP4, WebM, OGG, MOV — up to 60 MB
The library Required unless you are a moderator: "Choose one of your libraries for this image"

An SVG is read at the door. It is a document, not a rectangle of pixels: it can carry script, it can fetch, and it is served from this site's own origin. It is checked and sanitised on upload rather than trusting that every place it is ever shown will be an <img>.

The asset is embedded for semantic search on upload; a failure there is picked up by the retry sweep rather than failing the upload.

This is not the same intake as an article figure

POST /articles/{id}/figures/image — attaching a picture to a section — has its own, stricter rules: PNG/JPEG/WebP up to 8 MiB, clips up to 25 MiB, the type sniffed from the file's magic bytes, a caption required, and credit required for an attribution licence. See Figures.

The library upload above is the general one. Both end in the same asset table.

Describing one

The thing that makes an image findable, and the reason the upload message says "Uploaded. Describe it so it can be found."

Title, caption, alt text, source and source URL, licence, modality, category, tags, and the library it sits in — all through PATCH /media/{id}.

Modality is recorded by a person, never inferred from where the file came from: radiograph, ultrasound, CT, MRI, fluoroscopy, nuclear, photograph, histology, illustration, diagram, chart.

Licence and credit live on the asset, not in the prose, so the same figure used in three articles is cited the same way in all three. A no-derivatives licence is recorded and blocks the overlay tool.

Overlays

Vector shapes drawn on top of the picture — arrows and labels pointing at what matters — stored in normalised coordinates so they survive any size the image is shown at. The design note is Image overlays.

Filtering

Search (hybrid, over what the asset says about itself), library, and sourcequestion, article or unused. Source is not a column: a figure is a question's or an article's because something points at it, and the same drawing can be both. unused is how you find what nothing points at.

60 to a page, 200 at most.

managing=true — the reason this page is not the reading list

GET /media/ has two doors for a non-moderator: a library somebody granted you, or a figure hanging on an article you may already read. Reading needs the second one, or the grid would be empty for everybody but the editors.

managing=true closes it, and that is what this page asks for. Every card here carries Edit and the corner carries Upload, so the only honest list is the libraries this account holds — otherwise somebody with no library was shown 1,647 pictures, none of which they could touch.

One collection either way: a question's figure and a diagram drawn for an article are the same kind of thing to anybody looking for a picture of a topic. Where it came from is a filter, not a wall.

Deleting, and the bin

DELETE /media/{id}?force=true|false

Moderator only.

It is refused while a question still uses it"N questions still use this. Detach it there first, or delete it anyway." A question refers to a figure by id, so renaming it or moving it between libraries never breaks anything; deleting does, and silently, so the count has to be faced first. force=true gets past that check and buys nothing else.

Deleting is always soft. deleted_at is stamped and the bytes stay — the bucket is not versioned, delete sits one click from the thing you meant to press, and a borrowed radiograph cannot be re-sourced by hand.

It is also taken out of the prose that carries it: the figure line is stripped from every article that had it, because /uploads refuses a deleted asset and leaving the markdown behind put a broken image in the middle of somebody's reading.

/media/trash

Every binned asset you could have seen undeleted — trash is not a way round a grant — with how many days are left rather than the date it went, because the question in front of a bin is "how long have I got".

Restoring re-appends the figure line to every section it used to be in, at the end of the section: the section may have been rewritten meanwhile.

TRASH_DAYS = 30. The daily purge_trashed_media job is the only scheduled job in the system that destroys anything — see Figures and the bin and Background work.