The image library is a first-class catalog of images that lives alongside your diagrams, not inside them. Instead of embedding image bytes directly in BPMN XML, each image is stored once and referenced by its ID via theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Aston2710/mc-modeler/llms.txt
Use this file to discover all available pages before exploring further.
flujo:linkedImages attribute on BPMN elements. This keeps diagram files small, prevents duplication, and lets images be shared across multiple elements or diagrams within the same project.
Images are versioned and stored independently of diagram XML. Deleting or trashing a diagram does not delete its linked images. The images remain in the library and can be reattached to other elements or new diagrams at any time.
The LibraryImage interface
The ImageFolder interface
projectId is null). A folder cannot contain images from a different project.
The ref field
The ref field on a LibraryImage is a lightweight pointer that resolves image bytes on demand:
| Mode | ref format | Storage backend |
|---|---|---|
| Cloud (Supabase) | storage://diagram-images/<scopeId>/imglib/<uuid>.<ext> | Supabase Storage bucket diagram-images |
| Local | local://<id> | Browser IndexedDB via LocalImageRepository |
<scopeId>/imglib/<uuid>.<ext> where scopeId is the project_id (or owner_id for loose images). The imglib segment distinguishes library images from diagram-embedded image assets that share the same bucket.
The ImageThumb component resolves bytes on demand through imageStore.resolve(id), which checks an in-memory cache first (resolved map), then fetches from the appropriate backend. The result is cached so each image is fetched at most once per session.
Uploading images
Open the image library via the Images button in the main toolbar or top action bar. Click Upload (or drag and drop files onto the gallery grid) to open a file picker that accepts anyimage/* MIME type.
Before persisting, each file passes through fileToCompressedDataUrl (src/utils/imageCompress.ts), which re-encodes the image to reduce storage footprint. The compressed data URL is then passed to imageStore.upload():
Organising images into folders
The gallery sidebar lists all folders in scope. Click New folder, enter a name, and confirm. Duplicate names within the same scope are rejected client-side before hitting the database. To move an image to a different folder, use the folder dropdown that appears on the image card when hovering in management mode. This callsimageStore.move(id, folderId), which issues a targeted update to the folder_id column.
To delete a folder, click the trash icon next to its name in the sidebar. The folder record is removed and any images previously assigned to it have their folderId cleared to null — the images remain in the library, now in the “All” view.
Linking images to BPMN elements
Images are linked to diagram elements through the ImageContextPad — right-click any BPMN element to open the context menu, then select Link image. This opens the image library in picker mode (onPick prop), where clicking an image calls the attach handler, writing the image ID into the flujo:linkedImages attribute of the element in the diagram XML.
An image badge (rendered by ImageBadgeModule) appears on elements that have one or more linked images, showing the count. The badge is part of the bpmn-js overlay system and does not affect diagram export.
To detach an image, right-click the element and select Remove link from the ImageContextPad.
The ImageGallery component
TheImageGallery component is a full-screen modal that provides the complete library management experience:
- Sidebar: folder list for the current project scope, with New folder and delete actions.
- Search: filters images by name within the active folder.
- Grid:
ImageThumbcards that lazy-resolve image bytes. Each card shows rename, move-to-folder, and delete actions. - Drag & drop: files dragged onto the grid are uploaded immediately.
- Picker mode: when opened from a BPMN element context action, clicking a card calls
onPick(image)instead of managing the image, then closes the gallery.
ImageThumb: on-demand resolution
ImageThumb is a lightweight component that shows a placeholder until the image bytes are resolved:
object-fit: cover with object-position: top so that document-style content (titles, labels) visible at the top of the image is not cropped.
Real-time sync
In cloud mode, any image or folder created, renamed, or deleted by a collaborator is reflected in all open sessions automatically. This is powered by Supabase Realtime subscriptions set up inimageStore.startRealtime():
loadAll() refresh. The resolved bytes cache is preserved across refreshes — already-viewed images are not re-downloaded.
This behaviour was introduced in migration 0017_image_library_realtime.sql, which enables replica identity full on both tables and adds them to the supabase_realtime publication:
Storage and access control
In cloud mode, images are stored in the private Supabase Storage bucketdiagram-images (created by migration 0016_image_library.sql). Row Level Security policies on both the images and image_folders tables, and matching Storage object policies, enforce the same access model as diagrams:
- The image owner always has full access.
- Project collaborators inherit access according to their role:
editorandownercan upload, rename, move, and delete;viewercan only read.
Local mode
When Supabase is not configured, MC Modeler runs entirely in the browser. Images are stored in IndexedDB viaLocalImageRepository. The ref field uses the local://<id> scheme, and bytes are retrieved directly from IndexedDB without any network request. Real-time sync is not available in local mode.