User guide for the Media Management feature in GeoHazardWatch.
The Media Management feature allows GeoHazardWatch to browse, search, and display media files — photos and videos — stored on external drives or local folders, without moving or modifying the source files. It is designed for large personal or family photo libraries (500,000+ files).
| Property | Value |
|---|---|
| Source files | Never modified or moved |
| Index | Persistent JSON, updated on demand |
| Metadata | EXIF / IPTC / XMP (via ExifTool) |
| Thumbnails | Generated on first request; cached |
| Browse | By year, by keyword, or full-text search |
| Private awareness | Items linked to private pages are hidden from unauthorised users |
The feature is disabled by default. An administrator must enable it and configure at least one media folder before it is accessible.
The Media Management feature must be enabled and configured by an administrator before users can browse media.
ngdpbase.media.enabled must be set to truengdpbase.media.foldersIf these prerequisites are not met, all /media/* URLs return 503 Service Unavailable.
URL: /media
The media home page displays a grid of years for which at least one media item has been indexed. Click any year to see the items from that year.
URL: /media/year/{year}
The year page displays a thumbnail grid of all items indexed for that year, sorted by filename. Each card shows:
Click any card to open the Item Detail Page.
URL: /media/keyword/{keyword}
The keyword album page displays a thumbnail grid of all indexed media items whose EXIF/IPTC/XMP keyword list contains the specified keyword. Keyword matching is exact and case-sensitive.
The page shows:
?keyword={keyword} so that Prev / Next navigation stays within the keyword album rather than the yearMolly will show an album icon that navigates to /media/keyword/Molly.[{MediaPlugin format='album-link' keyword='...'}] plugin syntax (see Embedding Media in Pages)./media/keyword/{keyword} in the browser.URL: /media/search
The search page provides a free-text search across the media index. All query words must appear somewhere in the item's metadata for the item to appear in results (AND semantics).
| Field | Example |
|---|---|
| Filename | IMG_1234.jpg |
| Year | 2023 |
| EXIF title | Summer Vacation |
| EXIF description | At the beach |
| EXIF/IPTC keywords | family, holiday |
birthday 2022 finds items matching both birthday and 2022.birth matches birthday.URL: /media/item/{id}
The item detail page shows:
?keyword=), Prev/Next moves within that keyword's items./media/keyword/{keyword} to browse all media with that keyword.[{MediaPlugin ...}] snippets for each keyword on the item. Copy a snippet and paste it into any page to embed a list or album of items with that keyword. If no keywords are present, a generic [{MediaPlugin format='list' keyword='current'}] snippet is shown.For programmatic access, the same data is available as JSON:
GET /media/api/item/{id} — single item metadata
GET /media/api/year/{year} — all items for a year
The [{MediaPlugin}] plugin lets you embed live media counts, lists, or thumbnail galleries on any page.
[{MediaPlugin}]
[{MediaPlugin format='count'}]
[{MediaPlugin format='list'}]
[{MediaPlugin format='album'}]
[{MediaPlugin format='album-link'}]
| Parameter | Values | Description |
|---|---|---|
format | count (default), list, album, album-link | Output format |
keyword | any keyword string, or 'current' | Filter by EXIF/XMP keyword |
page | any page name, or 'current' | Filter by linked page name |
year | four-digit year | Filter by year |
max | integer | Maximum number of items to display |
Only one filter (keyword, page, or year) should be used at a time. If none is given, all indexed items are included.
Outputs the number of matching items as plain text.
[{MediaPlugin}]
Outputs: 14327 (the total number of indexed items)
[{MediaPlugin format='count' keyword='current'}]
Outputs: the count of items whose keywords include the current page name.
Outputs a bulleted list of filenames, each linking to its item detail page.
[{MediaPlugin format='list' keyword='Molly'}]
[{MediaPlugin format='list' year='2023' max='10'}]
[{MediaPlugin format='list' page='current'}]
Outputs an inline thumbnail grid. Each thumbnail links to the item detail page, and the link includes ?keyword={keyword} when a keyword filter is active so that Prev/Next navigation on the detail page stays within the album context.
[{MediaPlugin format='album' keyword='current'}]
[{MediaPlugin format='album' keyword='Summer 2024' max='20'}]
For keywords that contain an apostrophe, use double quotes around the value:
[{MediaPlugin format='album' keyword="Molly's Cooking"}]
Outputs a styled button that links to the /media/keyword/{keyword} album page. The button shows the keyword name and item count.
[{MediaPlugin format='album-link' keyword='current'}]
[{MediaPlugin format='album-link' keyword="Molly's Cooking"}]
Note: format='album-link' requires a keyword= parameter. It returns an error message if no keyword is provided.
Both keyword='current' and page='current' resolve to the current page's name at render time. This makes the plugin portable — you can add the same snippet to many pages and each page will automatically show its own related media.
[{MediaPlugin format='album' keyword='current'}]
On the page named Molly, this is equivalent to:
[{MediaPlugin format='album' keyword='Molly'}]
Show a count of all indexed media items:
This platform has [{MediaPlugin}] media items indexed.
Show a thumbnail album of photos tagged with the current page's name:
[{MediaPlugin format='album' keyword='current'}]
Show a link button to a specific keyword album:
[{MediaPlugin format='album-link' keyword='Family Holidays'}]
Show the first 10 items from 2022 as a list:
[{MediaPlugin format='list' year='2022' max='10'}]
Show all media linked to the current page by page association:
[{MediaPlugin format='count' page='current'}] photos are linked to this page.
[{MediaPlugin format='list' page='current'}]
To embed a single media library photo inline in page content — rather than a full album — use the media:// URI with Using ImagePlugin or Using AttachPlugin:
[{Image src='media://IMG_1234.jpg' caption='Family Trip 2024' align='center'}]
[{Image src='media://DSC_0042.jpg' align='left' display='float'}]
[{ATTACH src='media://vacation.jpg' caption='Summer 2024'}]
Use the original filename (e.g. IMG_1234.jpg) exactly as it appears in the media index. The file is served from /media/file/:id; items linked to Private Pages are only visible to authorised users.
For layout options (align, display, caption, width, etc.) see Attachments, Using ImagePlugin, or Using AttachPlugin.
URL: /media/thumb/{id}?size={WxH}
Thumbnails are generated on the first request and cached to disk. Subsequent requests for the same item and size are served from the cache instantly.
Default sizes used by the browser UI: 300x300 (grid), 800x600 (detail).
Any WxH value can be requested via the API. Thumbnails are always JPEG at 85% quality, cropped to fit the requested dimensions (cover mode).
Video files do not have thumbnails in the current version — a film icon placeholder is shown instead. Video playback is available on the item detail page via the HTML5 <video> element.
The list of indexed file extensions is configurable via the ngdpbase.media.extensions config key. The default set is shown below.
| Extension | Format |
|---|---|
| jpg, jpeg | JPEG |
| png | PNG |
| gif | GIF |
| heic, heif | HEIF / HEIC (Apple) |
| tiff, tif | TIFF |
| webp | WebP |
| raw, orf, cr2, nef, arw, dng | Camera RAW formats |
| bmp | Bitmap |
| Extension | Format |
|---|---|
| mp4 | MPEG-4 |
| mov | QuickTime |
| avi | AVI |
| mkv | Matroska |
| m4v | iTunes Video |
| wmv | Windows Media Video |
| 3gp | 3GPP Mobile Video |
To add or remove extensions, set ngdpbase.media.extensions to the desired list in your instance configuration. For example, to also index .flv and .webm files:
ngdpbase.media.extensions = ["jpg", "jpeg", "png", "mp4", "mov", "flv", "webm"]
The leading dot is optional — both "jpg" and ".jpg" are accepted. Values are normalised to lowercase.
In your instance configuration (or app-custom-config.json), set:
ngdpbase.media.enabled = true
ngdpbase.media.folders = ["/path/to/photos", "/path/to/more-photos"]
Restart the server after changing these settings.
URL: GET /admin/media
The admin media page shows the current index statistics (number of years indexed, year range) and a Trigger Rescan button.
Clicking Trigger Rescan sends a POST /admin/media/rescan request. The scan runs synchronously and the page shows a summary of the result:
For very large libraries the scan may take several minutes. The browser will wait for the response.
The server automatically re-scans all configured folders on a schedule. The default interval is every hour (3600000 ms). Configure with:
ngdpbase.media.scaninterval = 3600000
Set to 0 to disable background scanning.
All settings live in the ngdpbase.media.* namespace.
| Key | Default | Description |
|---|---|---|
ngdpbase.media.enabled | false | Enable the media feature |
ngdpbase.media.folders | [] | Absolute paths to media root folders |
ngdpbase.media.maxdepth | 5 | Maximum directory depth (0 = unlimited) |
ngdpbase.media.scaninterval | 3600000 | Background rescan interval in ms |
ngdpbase.media.ignoredirs | [".dtrash", ".ts"] | Directory names to skip during scan |
ngdpbase.media.ignorefiles | [".photoviewignore", ".plexignore"] | Sentinel files that exclude a directory |
ngdpbase.media.extensions | *(see Supported File Formats)* | File extensions to index (overrides built-in list) |
ngdpbase.media.index.file | *(data dir)* | Absolute path to media-index.json |
ngdpbase.media.thumbnail.dir | *(data dir)* | Absolute path to thumbnail cache directory |
ngdpbase.media.thumbnail.sizes | 300x300,150x150 | Comma-separated size specs |
ngdpbase.media.metadata.priority | ["EXIF","IPTC","XMP"] | Metadata extraction priority |
ignoredirs — any directory whose name exactly matches an entry in this list is skipped entirely (and its children are not scanned).ignorefiles — if a directory contains a file with one of these names, the entire directory (and its children) is skipped. This is compatible with the .photoviewignore and .plexignore conventions used by other photo management tools.Thumbnail generation for video files requires FFmpeg, which is not currently bundled. Video items show a placeholder icon in the grid and detail views. Video playback is supported in the item detail page via the browser's native HTML5 <video> player.
The media feature is strictly read-only. It never modifies, moves, renames, or deletes source media files.
The index is empty until the first scan completes. Year browsing and search return no results before then.
Background scans compare each file's modification time against the index. If you replace a file with new content but preserve the modification time, the change will not be detected unless you trigger a forced rescan from the admin page.
See Media for an overview, Attachments for uploading files, and Using ImagePlugin, Using AttachPlugin, and Using MediaPlugin for plugin parameter references.