Media
Upload images and documents once and use them everywhere: the media manager stores each image at four sizes, converts it to WebP, crops to a ratio or a free shape, keeps PDFs, Word, Excel, PowerPoint, CSV and text files for pages to link to, takes images from the pages of a PDF, and finds anything by its title, notes or alt text.
What it is
The media manager is at Media Manager in the admin menu (/admin/media) and opens as a picker from every image field. It has these tabs:
| Tab | Gives |
|---|---|
| My Uploads | Every image in the library, newest first, 20 per page. Drop or choose several files at once. A PDF dropped here opens Take an image (in a picker, on From a PDF) and is kept in Files; any other document goes to Files. |
| From a PDF | Take an image from a PDF and insert it in one go. See From a PDF. In every image picker; not on the Media Manager page, where Files has Take an image. |
| Files | Documents: PDF, Word, Excel, PowerPoint, CSV and text files, newest first. See Files. Always shown on the Media Manager page; in a picker only when the caller asks for files. |
| Free Images | Search Unsplash photos, once an Unsplash key is set in Settings > Integrations. A chosen photo is used from Unsplash by its URL; it is not copied into your storage. |
| Icons | The Font Awesome icon picker. Shown only when an icon field opens the picker. |
Where the picker opens:
- The content editor: cover image,
imagefields, images in the body, and rows of gallery and info card fields (a gallery can take several images in one pick). An image dropped or pasted into the body goes to the library without the picker; see Drop or paste into the editor. - The content editor's
filefields and the body's Attach files command (type/in the body), which open it on Files. See File fields. - The signup form editor.
- The logo in Settings, About.
- An admin's profile photo. Members upload their photo to their own folder instead (
avatars/{uid}/); they never see the library.
The picker is as wide as the window is tall (a wide dialog on a computer) but never wider than the screen. On a phone (and any window up to 768px wide) it takes the screen's width and the tabs become a dropdown. Choosing an image, icon or file opens its details over the images, with Insert; Back returns to the images. When the picker takes several at once, picking keeps the images in view and Insert is in a bar below them. Crop and Take an image open their step at the top, and Cancel in the crop step returns to the details. The Media Manager page works the same way.
Turn it on or off
Media is always on. It is core and belongs to no switchable feature.
Set it up
Nothing is needed: uploads work on a new install. To change the limits, open Settings > Misc, Media Upload:
| Setting | Default | Stored as |
|---|---|---|
| Max File Size (MB) | 5 | Settings/misc.mediaMaxFileSize |
| Max image size (px, longest side) | 1200 | Settings/misc.mediaMaxSize |
| Convert all images to WebP | On | Settings/misc.mediaConvertToWebp |
To offer Unsplash, add an Unsplash access key under Settings > Integrations; the page has a setup guide. For choosing and organizing a website's images, see Manage media.
Use it
Upload
The manager accepts JPEG, PNG, WebP and GIF. Each file is processed in the browser, then uploaded:
It is resized to four sizes, each a limit on the longest side, so a size means the same box for landscape and portrait photos.
It is encoded as WebP (unless conversion is off). A size the image is too small for is not enlarged; sizes with the same pixel size share one file.
The largest file is checked against the file size limit. Too large, and the upload stops with a message.
The files go to Storage and one
mediadocument records them.
| Size | Longest side | Default | Typical use |
|---|---|---|---|
| S | A quarter of the maximum | 300px | Thumbnails, list cards |
| M | Half | 600px | The size an editor gets unless they choose |
| L | Three quarters | 900px | Article bodies |
| XL | The maximum | 1200px | Covers, heroes, the social share image (the cover picker opens at XL) |
GIFs are stored once, as they are, so animation survives: they have no sizes.
Files
The Files tab keeps documents for pages to link to. Drop files on the Upload file card, or choose them (several at once). The type is decided by the file's extension, not by what the browser reports, and only these are taken:
| File | Extensions | A visitor's browser |
|---|---|---|
.pdf | Opens it in a tab | |
| Word | .docx, .doc | Downloads it |
| Excel | .xlsx, .xls | Downloads it |
| PowerPoint | .pptx, .ppt | Downloads it |
| CSV | .csv | Downloads it |
| Text | .txt | Opens it in a tab |
- Files can be up to 20 MB each. There is no setting for it: documents are stored as they are, not resized like images.
- Pages, SVG, scripts, ZIP archives and macro files (
.docm,.xlsm) are refused, with a message naming the file. The storage rules refuse them too. - Each file gets a title from its name ("Annual-Report_2025.pdf" becomes "Annual Report 2025"). The title is what the library shows, the link text on pages, and the name a download is saved under.
- A PDF shows its first page on its card and its page count in the panel. A PDF locked with a password, or one that cannot be read, still uploads; it shows a PDF icon instead.
Anyone with a file's link can open it, as with images: published pages link to them. Keep private documents out of the library.
Select a file to see its panel: type, size, pages, upload date and stored name, its details, and Copy link, Open and Delete. A PDF also has Take an image. Word and PowerPoint files say to save them as a PDF to take images from them.
Take an image from a PDF
Pull a photo or a chart out of a brochure without another program. Open a PDF one of these ways:
- In any image picker (Insert image in the body, an image or gallery field): the From a PDF tab. See From a PDF.
- On the Media Manager page: drop or choose a PDF on My Uploads, or select one in Files and press Take an image.
A PDF from your computer opens at once and is kept in Files once it has opened, so you can come back to it. The same PDF (same file name and size) is not stored twice, and a PDF that will not open (locked or broken) is not kept. Each image records the PDF and page it came from, when the PDF is in Files.
The pages show as a grid, drawn as they come into view, so a long PDF opens quickly.
Click a page. It opens in the same crop step as Crop, with the pictures on the page outlined and numbered. The frame starts on the first picture not taken yet, reading top to bottom, then left to right.
Click another outline (or a picture's number) and the frame takes that picture's exact edges (with a fixed ratio picked, the largest frame of that ratio centred on it), or drag the frame anywhere; a press inside the frame always moves it, for a label, a chart or part of a photo. Pictures already taken in this visit show a tick.
Zoom with the minus and plus buttons, Ctrl or Cmd with the mouse wheel (a trackpad pinch works the same way in Chrome, Edge and Firefox, not in Safari), a two-finger pinch on a touch screen, or the + and - keys while the frame has focus; drag outside the frame to move around. The page is drawn again with more detail as you zoom. Move between pages with the arrows, by typing a page number, or with Page Up and Page Down; All pages goes back to the grid.
Save as image (in a picker, Insert or Save, take another) draws only the framed part again, at the XL size, and uploads it like any image: every size, WebP when that is on, named after the PDF and the page ("Brochure, page 3"; a second one from the page is "Brochure, page 3 (2)"). Text and drawings come out sharp; a photo inside the PDF is only as sharp as the photo the PDF holds, and the usual note says when the result is smaller than the size picked.
After a save the page stays open, with the frame on the next picture not taken. On the Media Manager page, Done on the page grid opens My Uploads with the newest image selected.
The PDF is never changed, and what is saved is always the framed part as the page shows it: never text, and never a picture's own file pulled out of the PDF. A PDF locked with a password says so and asks you to remove the password first; there is no password box.
Pictures are found from how the page is drawn, so they are exact to the point. Some things are not offered, and need a dragged frame:
- Artwork drawn with shapes, such as charts, logos and illustrations, rather than a picture.
- A scanned page: the whole page is one picture, so nothing on it is offered.
- Small pictures (under two thirds of an inch on a side), such as icons and bullets.
A picture partly hidden by a shape, such as a photo in a circle, is outlined at its full size; drag the frame in if you want less. Pieces of one photo cut into strips are joined into one.
From a PDF
The tab every image picker has for taking images from a PDF and inserting them, made for a brochure whose photos go in different places on a page:
Choose Insert image (or open any image field's picker) and click From a PDF. It lists the PDFs in Files, newest first, with the one you used last first of all, under Choose a PDF from your computer (or drop one on the tab). With more than six, a search box finds them by title, notes or file name.
Click a PDF, then a page. Frame a picture as in Take an image from a PDF, and if you like, type its alt text and pick the size.
Press Insert. The image is saved to My Uploads and goes in, at that size and with that alt text.
For the next photo, choose Insert image again: the picker opens on the same PDF and page, at the same zoom, with the frame on the next picture not taken. Press Insert.
The picker opens on the PDF only when the last image you chose came from one; choose an image from another tab and it opens as usual again. A picker that asks for its own first tab (an icon field, for example) always opens there. This is remembered in the browser tab until you reload the admin, and the PDF is read from Storage once per visit, not each time the picker opens. In the body, the cursor moves past each inserted image, so the next one goes after it.
Save, take another saves without inserting, for photos you will use later; they are in My Uploads. In a field that takes several images (a gallery), Insert adds every image taken in that visit, from any PDF, in order, and says how many.
Details and search
Every image and file has details, edited in its panel and saved when you leave the field:
| Detail | For | Used |
|---|---|---|
| Title | Images and files | What the library shows; for a file, its link text and download name. Starts as the file name. Cleared, it goes back to the file name. |
| Alt text | Images | Describes the image for screen readers and search engines. Put in the image's alt when it is inserted in the body. A content image field stores only the URL, so templates keep their own alt. |
| Notes | Images and files | Only staff see them. Words here help you find the item later. |
The search box on My Uploads and Files finds items whose title, notes, alt text or file name hold every word typed, in any order, ignoring case and accents ("pune brochure" finds "Spring brochure" with the note "For the Pune store"). The first search loads the tab's details once; clear the box to page through the library again. Images uploaded before details existed show their file name until given a title.
Drop or paste into the editor
Drop an image onto the rich text editor, or paste one (a screenshot, or an image copied in a browser), and it is uploaded exactly as above: the same settings, sizes, WebP conversion and media document, so it shows in My Uploads. While it uploads, a box where it was dropped shows the file name and how far the upload has got. The image then goes in at M, the size Insert image gives unless you choose. Several images dropped together upload one after another and keep their order.
- A file of the wrong type or too large is not added, and a message says why.
- If the upload worked but its
mediadocument could not be saved, the image still goes in, and a message says it is not in My Uploads. - A paste that carries text as well, such as cells copied from a spreadsheet or a passage from a word processor, pastes the text, not the picture of it those programs also put on the clipboard.
- A document the library takes (PDF, Word, Excel, PowerPoint, CSV or text) is uploaded to Files the same way and goes in as a file card: a link with the file's title, type and size.
- Any other file is not added, and a message says it cannot be uploaded.
The editor never puts an image's bytes into the content (as a data: URL): that would make the entry document large, towards Firestore's 1 MiB limit, and skip the sizes.
Pick an image
In the picker, choose an image and a size (S, M, L or XL), then confirm. The field stores that size's URL. Templates can still use any other size of the same image through {{ key_s }} to {{ key_xl }}; see Templates.
Crop
Select one image and press Crop under its preview. The crop step takes the place of the grid:
- Pick a ratio: Free, Original (the image's own shape), 1:1, 4:3, 3:4, 3:2 or 16:9. The frame starts as the largest centred one of that shape (Free starts as the whole image).
- Drag inside the frame to move it, and drag a corner or an edge to resize it. With a ratio, every handle keeps it. The arrow keys move the focused frame, with Shift for bigger steps.
- Below the image is the size the crop will be. When it is smaller than the size picked in the side panel, a note says so: the image is never enlarged, so it may look soft in a large space.
What applying a crop does depends on where the image comes from:
| Image | Applying the crop |
|---|---|
| An upload (My Uploads) | Save cropped copy saves the crop as a new image, at all four sizes, and selects it. The original is not changed, because content may already use it. The copy is cut from the original's XL file, the largest one kept, and goes through the same size, WebP and file size rules as an upload. |
| An Unsplash photo (Free Images, in the picker only) | Apply crop keeps the crop for this pick. Nothing is copied: the inserted URL asks Unsplash for the cropped photo (its rect setting, in the photo's original pixels), so the photo is still used from Unsplash. Every size a template derives keeps the crop. Remove crop goes back to the whole photo. |
Crop is not offered for GIFs (it would drop the animation), or when the picker is choosing several images at once.
Delete
Deleting an image removes every stored size from Storage and the media document. Deleting a file removes it, its first-page picture and its mediaFiles document; images taken from it stay.
Delete does not check whether content uses the image or file. Pages that show or link to it break, including published pages. Search your content before deleting.
Move media to another project
Data > Export Files and Import Files copy images and files, with their titles, alt text and notes; see Data import and export.
Extend it
- Open the picker from your own admin page by opening
MediaManagerComponent(insrc/app/pages/admin/(media)/media.page.ts) as a dialog withmediaPickerDialogConfig({ isDialogOpen: true })fromsrc/app/pages/admin/(media)/media-picker-dialog.ts, which gives it the picker's size, so it fits a phone, and its styles:dialog.open(MediaManagerComponent, mediaPickerDialogConfig({ isDialogOpen: true })). Options:multiple(several images or files),size(the preselected size),cropRatio(the ratio the crop frame opens with, such as'1:1'for a square slot; Free when omitted),allowIcons,allowImagesandallowFiles(which tabs show; files are off unless asked for, so a caller that only knows images never gets a document), andinitialTab. It returnsmediaUrl,mediaUrls,sizeandkind; for an image with alt text,alt; for files,file(orfileswithmultiple), each{ id, url, title, type, bytes, pages }, withmediaUrlthe first file's URL. For a files-only picker pass{ isDialogOpen: true, allowFiles: true, allowImages: false, initialTab: 'files' }. - Upload an image from your own admin code the way a drop into the editor does with
EditorImageUploadService.upload(file, onProgress)(insrc/shared/components/tiptap-editor/service/editor-image-upload.service.ts). It reads the settings, uploads every size, writes themediadocument and resolves to the M size's URL; it rejects with a message fit to show for a wrong type or a file too large. - Upload a document the same way with
EditorImageUploadService.uploadDocument(file, onProgress): it goes to Files with itsmediaFilesdocument and resolves to{ url, title, type, bytes, pages }. - The allowed types, the 20 MB limit and the helpers (
allowedFileOf,defaultTitle,formatBytes,isSameUpload) are insrc/shared/utils/media-files.ts;openPdfinsrc/shared/utils/pdf-pages.tsdraws PDF pages in the browser (pdf.js, loaded only when used), and itsfindPictures(page)gives the pictures on a page in reading order, in page points (picturesFromOperatorsdoes the work,snapFramefits a frame of a ratio on one). - The crop frame,
ImageCropperComponent(insrc/shared/components/image-cropper/), takes three optional inputs besidessrcandratio:frame(a frame to place, in image pixels),zoom(1 fits the image; withzoomableon, the wheel, a pinch and the keys ask for another zoom throughzoomChange) andmarks(outlines to click, reported bymarkPicked). - Files your app lets members upload belong in their own folders under rules you write in
storage.app.rules. See Set security rules and indexes.
What it stores
| Where | What |
|---|---|
Storage mediaImages/{name}-{random}-{size}.webp | The sized files (-s, -m, -l, -xl); the original extension instead of .webp when conversion is off. GIFs: mediaImages/{name}-{random}.gif. The name comes from the file name, lowercased and hyphenated. A cropped copy is named after its original with -crop. With an upload folder configured for the install, every path starts with it (see Configure a project). |
media/{id} | downloadURL (the XL file), name, title, uploadTime, width, height, and variants: for each size its url, Storage path, width and height. GIFs have no variants. A cropped copy is a document like any other upload. Optional: alt, notes, and for an image taken from a library PDF source: { fileId, page }. |
Storage mediaFiles/{name}-{random}.{ext} | A file, stored as it was uploaded, with its content type and whether it opens or downloads (under its title). A PDF's first page: mediaFiles/{name}-{random}-thumb.jpg. |
mediaFiles/{id} | title, name, downloadURL, path, type (pdf, word, excel, powerpoint, csv or text), contentType, bytes, uploadTime; for a PDF pages and thumbnail (url, path, width, height); optional notes. |
Settings/misc | The upload settings above |
Settings/integrations | The Unsplash keys (admin only) |
| Cloud Function | Kind | Does |
|---|---|---|
searchUnsplash | Callable | Searches Unsplash with the key kept server-side, 20 results per page |
readMediaImage | Callable | Admins only: returns the bytes of an upload's XL file (from its media document, never a path the caller names) so the browser can crop it. GIFs and files over 7 MB are refused. |
readMediaFile | Callable | Admins only: returns a library PDF (from its mediaFiles document) in parts of 6 MB, so the browser can draw its pages for Take an image. One reply holds about 10 MB, so a 20 MB PDF takes four calls. Other types and files over 20 MB are refused. |
Resizing and cropping happen in the browser; no function processes uploads. To crop an upload, the browser gets its XL file's bytes through readMediaImage, because a canvas may only export an image its page is allowed to read, and a Storage bucket sends no cross-origin header unless it was given a CORS setup. The crop frame itself shows the image by its normal URL, so it appears at once; the bytes are fetched on Save cropped copy. A PDF's pages are drawn with pdf.js the same way: from the file on your computer, from this visit's upload, or through readMediaFile.
Who can do what
| Resource | Read | Write |
|---|---|---|
Storage files (outside users folders) | Anyone | Admins (and the reserved editor role) |
media and mediaFiles documents (titles, alt text, notes) | Admins and editors | Admins and editors |
Storage mediaFiles/ | Anyone | Admins and editors, only the allowed types, each extension with its own content type, up to 20 MB |
avatars/{uid}/ | Anyone | That signed-in user, images under 5 MB |
Storage is public to read because published pages show the images and link to the files. The details are staff only so notes stay private; pages never read them. See Security rules.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| "... exceeds the maximum allowed size" | The XL file is over the limit. Raise Max File Size, or lower Max image size. |
| "Invalid file type" | Only JPEG, PNG, WebP and GIF are accepted. Convert SVG, HEIC or other files first. |
| "Could not add photo.jpg: the upload did not finish" | An image dropped or pasted into the editor could not reach Storage: the network dropped, or the account may not write to Storage. Try again; if it keeps failing, upload it from Media Manager to see the full error. |
| "The image is in place, but it could not be added to My Uploads" | A dropped or pasted image was stored and inserted, but its media document was refused (often the Firestore rules are not deployed). The page shows the image; only the library does not list it. |
| "this type of file can't be uploaded" | Files takes PDF, Word, Excel, PowerPoint, CSV and text files. Save other documents in one of those formats; put images in My Uploads. |
| "... is 24.9 MB. Files can be up to 20 MB." | Make the file smaller (in a PDF program, save a reduced-size copy) or split it. |
| No outlines on a page that has photos | The page is a scan (one picture for the whole page), or its "photos" are drawn with shapes. Drag the frame around the part you want. |
| From a PDF opens on a PDF you finished with | The last image you chose came from it. Click All PDFs, or choose an image from another tab once; a reload also forgets it. |
| A PDF shows an icon, not its first page | It is locked with a password or could not be read. It still works as a link; Take an image needs an unlocked copy. |
| Part of a PDF page is blank in Take an image, or its text looks different | The page uses a JPEG 2000 picture or a font the PDF does not carry (common in Chinese, Japanese and Korean PDFs). Pages are drawn in the browser without extra decoders or font data, so those parts can be missing. Export the page to an image in a PDF program and upload that instead. |
| "This PDF is locked with a password" | Remove the password (print or export an unlocked copy), then upload or drop that. |
| "Could not read the PDF" on Take an image | The network dropped, the functions are not deployed since files were added (readMediaFile is missing), or the account is not an admin. |
| A search finds nothing you expected | Every word must match. Older images have no title or notes until you add them; their file name still matches. |
| Free Images asks for setup | No Unsplash access key in Settings > Integrations. |
| Upload fails with a permission error | The account is not an admin, or the Storage rules are not deployed. |
A size binding such as {{ coverImage_l }} shows a broken image | The upload was smaller than that size's limit, so that size shares a larger size's file and the derived address has no file. Upload images at least as large as Max image size. |
| Size bindings are empty | They are derived only for Media Manager uploads (under mediaImages/, in the install's upload folder if it has one) and for Unsplash photos. An image pasted from elsewhere gets none: bind the stored URL. |
| Changing Max image size did nothing to old images | Settings apply to new uploads only. |
| No Crop button | The image is a GIF, the picker is choosing several images, or it is an Unsplash photo on the Media Manager page itself (crop it in the picker, where it is inserted). |
| "Could not load the image to crop" | The image's file is gone from Storage or Unsplash, or the network dropped. Reload and try again. |
| "Could not save the cropped image" with a permission or not-found error | The functions are not deployed since cropping was added (readMediaImage is missing), or the account is not an admin. Deploy the functions. |
| A cropped copy looks soft | The crop is smaller than the size used where it shows. Crop a larger area, or upload a larger original. |