Features
This page documents what the current repository actually implements.
Home
The home view is the primary feed surface.
It includes:
- three feed modes: Recent, Rediscover, and Random
- a top Moments or Highlights section
- feed-card avatar rings that can open an App Folder's avatar story in place when that folder has stories
- an active home-feed video player that promotes one visible video card at a time and gives that card play, mute, fullscreen, and seek controls
- feed-card actions for downloading the original media file and opening the original in a new tab
- bookmark actions that can save a post directly or manage its collection membership from a popover
- place links on feed-style cards when a photo has an assigned location
- scan progress states that distinguish discovery from later media-processing work while the library is being prepared
- a rebuild notice when the configured gallery root changed
- desktop recommendations for folders based on recency, likes, and recent navigation
- infinite loading for feed pagination
Feed videos pause when they scroll out of view, stopping their audio as well. Fullscreen playback continues until you exit fullscreen; scrolling then follows the same visibility rules without changing your saved sound preference.
The desktop recommendations sidebar scrolls with the feed. The Moments or Highlights rail shares the feed's center line. Desktop navigation and folder shortcuts are vertically centered between the logo and the More menu. Portrait windows use the centered feed layout without the recommendations sidebar.
Feed mode behavior
| Mode | What it does |
|---|---|
| Recent | "Newest posts first, with lighter runs from the same app folder." |
| Rediscover | "Older posts resurface when they are worth another look." |
| Random | "A fresh shuffle that stays steady while you browse." |
Reels
The dedicated reels view is available at /reels.
It includes:
- a video-only queue sourced from indexed library posts
- a full-height scroll-snap deck
- wheel, arrow-key, and page-up/page-down navigation in addition to direct scrolling
- infinite loading with prefetch as you approach the end of the current queue
- a desktop action bar for like/favorite toggle, details sidebar, folder shortcut, and original-video link
- a bottom-edge seekable progress UI shared with the feed and post players
- loading, empty, and error states
- an app-wide default mode from Settings; the page itself does not expose an inline mode switch
Queue behavior
| Mode | What it does |
|---|---|
| Recommended | "Affinity-ranked mix." It scores videos from a bounded candidate window using freshness, likes, recent folder affinity, portrait fit, duration fit, and a deterministic seed, then reduces immediate repeats from the same folder when alternatives exist. |
| Recent | "Newest videos first." Pages continue from an opaque cursor so tied timestamps cannot duplicate or skip videos. |
| Random | "Stable session shuffle." The same seed keeps the same order across pages, and changing the seed starts a new queue. |
For large libraries, Recommended describes its bounded session queue in total/hasMore rather than promising every video in one session. Starting a new Reels session with a new seed rotates the discovery sample.
Explore
Explore is a dedicated full-screen shell with a darker visual treatment.
It combines:
- a random feed source
- client-side ranking that boosts recent folder activity, liked folders, and recently opened folders
- folder search across name, slug, breadcrumb, and path
- local recent-search history stored in
localStorage
Folder search covers the complete indexed library and loads additional matches as you scroll. Searches do not depend on which folders have already appeared in Home or Library.
Library
Library lists indexed folders in pages, loading more as you scroll or select Load more. Its folder and post totals describe the complete library. Search and sorting apply across all indexed folders, including those you have not loaded yet.
Library supports:
- free-text search
- sorting by recent activity, post count, name, or path
- quick navigation into folders
- delete actions from a context menu
If a directory request fails, you can retry or change the search and sort controls. The whole-library totals update after scans and deletions even while a search is active.
Folder deletion behavior
Library supports two delete flows:
| Flow | Behavior |
|---|---|
| Delete app folder | Deletes the folder's media, including owned reserved stories and Carousel items, and their derivatives. Independent child App Folders are kept. The source folder is only removed if it becomes empty. |
| Delete folder subtree | Removes the source folder subtree from disk, removes the cached derivatives for its indexed media, and deletes all affected indexed folders below that path. |
Folder pages
A folder page is available at:
/f/:slug/folders/:slugas a legacy alias
Folder pages include:
- a folder header with avatar, posts counts, descriptions, and optional avatar-story opening
- editable folder name and description via an admin "Edit App Folder" flow
- an admin-only "Share folder" action for scoped read-only sharing
- long descriptions that collapse to two lines by default and expose an expand/collapse caret only when the text actually overflows
- a posts grid that follows the app-wide default folder order
- highlight circles above the posts and reels tabs when the folder has story capsules
- a reels tab when the folder contains videos
- infinite loading
The reels tab is a filtered view backed by the same folder endpoint using mediaType=video.
The post viewer also uses the same default folder order when resolving previous and next navigation within a folder.
Folder sharing
Admins can share one folder without creating user accounts or unlocking the whole library.
The Share Folder dialog supports:
- normal public folder URL copying when public viewer mode is enabled
- read-only links for one folder
- expiration presets for 1 hour, 24 hours, and 7 days
- custom expiration timestamps
- unlimited links that remain revocable
- reusable per-folder passwords
- revoking existing share links
- removing or changing the folder password to invalidate password sessions
Share links and password access are independent ways to open the folder. An active share link does not require the folder password, and revoking a link does not disable password access. The dialog shows every active access method and clarifies which methods remain available after an access setting changes.
Shared visitors use /share/:slug, not the normal authenticated folder route. They can browse only that folder and its shared post view. They do not get Home, Explore, Reels, Places, Settings, Likes, Collections, Trash, scans, rebuild actions, caption editing, cover editing, delete actions, or original-file downloads.
Shared thumbnails and previews are served through /api/share/images/:id/... after the server checks the folder grant for that image.
Folder stories and highlights
Foldergram can reserve AppFolder/stories as a story-style source for that folder.
In the default reserved-stories mode:
- direct media inside
AppFolder/storiesbecomes the folder's avatar story set - each direct child folder inside
AppFolder/storiesbecomes one highlight capsule - nested folders below a highlight are folded into that same capsule instead of becoming separate app folders
- story media is hidden from normal folder, feed, search, and reels surfaces
- the folder header avatar opens the avatar story when one exists
- Home feed cards can open the same avatar story from the folder avatar ring
- the shared stories modal is used for both the home-feed entry point and the folder-page entry points
- the shared stories modal header includes original-media download plus playback controls for the active story item
If the reserved root has no direct media but highlight capsules do exist, Foldergram can synthesize the avatar story from recent highlight media so the folder still has an avatar-story entry point.
Places
Places add an offline location layer for photos that already contain GPS metadata.
The current app includes:
- a dedicated
/placesdirectory page - search and sort controls for place name, country, and post counts
/places/:slugdetail pages with grouped posts- approximate-city labeling when the stored match is not exact
- location links on feed-style cards and inside post-viewer metadata
- a Places shortcut in navigation when indexed places exist
- Settings controls to prepare offline GeoNames data and rebuild place assignments
Post detail and modal flow
The canonical post detail route is /post/:id.
/image/:id remains available as a legacy alias.
Behavior depends on how the route is opened:
- from another page, it can render as a modal over the background route
- directly, it renders as a full page
The modal uses a centered, borderless media area with a consistent target width. Its height follows the photo or video's proportions, so wide posts leave more of the dimmed background visible. Very tall media scales down to fit the screen.
Portrait desktop windows and narrow screens start with details hidden. Use the sidebar button below the right navigation arrow to show or hide details. Details open over the media on these screens; on wider landscape windows, they appear alongside it and can also be hidden. Previous and next controls stay at equal distances from the screen edges, and Close stays in the top-right corner. For panoramic posts, docked details keep enough height for captions and metadata and scroll independently of the media.
The detail view includes:
- image detail media sourced from either generated previews or originals, depending on
IMAGE_DETAIL_SOURCE - video detail playback that uses the selected ordinary source: the original for qualifying direct-playback videos, or a generated preview otherwise
- an optional
HDtoggle for compatible higher-resolution MP4 originals that use a generated preview - previous and next navigation within the same folder and active media filter
- folder link and breadcrumb context
- caption text that uses a saved custom caption when present and otherwise falls back to a readable filename
- an admin-only inline caption edit action in the sidebar summary, with the same caption reflected across feed-style surfaces
- size, dimensions, MIME type, duration, and location metadata when available
- like toggle
- save and collection controls
- original-media download control
- original-file link
- an admin-only "Set as Cover" action to customize the folder avatar, which highlights dynamically if the image is already the cover
- trash and permanent-delete actions with confirmation for admin sessions only
After deleting the last post in a folder, the standalone detail view returns to Library. A modal detail view closes back to the page beneath it.
Saved posts, likes, and collections
Foldergram has two saved-items storage modes:
- signed-in
adminandviewersessions use shared SQLite likes and collections - anonymous public sessions use browser-local favorites and collections stored in
localStorage
Collections include:
- a default saved collection surfaced as
All Postsin the UI - custom collections with create, rename, and delete flows
- bookmark-popover collection membership management from feed cards and the post viewer
- dedicated
/collectionsand/collections/:slugroutes - syncing between the default saved state and custom collection membership
Likes remain separate from saved posts.
The likes view:
- shows liked or favorited posts ordered by the most recent toggle in that mode
- updates optimistically in the UI
- drops deleted or trashed posts automatically when they are removed
- stays intentionally separate from saved-post collections
There is no shared social layer behind any of these surfaces.
Trash
Trash is an admin-only recovery surface at /trash.
It includes:
- paginated deleted-post cards
- multi-select restore actions
- multi-select permanent-delete actions
- folder shortcuts for reviewing where a trashed post came from
- an empty state when nothing is currently trashed
Moving a post to Trash keeps the original file on disk. Permanent delete removes the original file, thumbnail, and preview.
Moments
Home and /moments/:id expose either:
- date-driven Moments
- fallback Highlights
The selected set depends on timestamp coverage in the current library. The UI uses the same route name for both and adapts to the returned payload labels.
This is separate from folder stories and folder highlights sourced from reserved stories/ folders.
Settings
Settings is the operational control surface for the library.
Its left sidebar is split into:
| Section | What it contains |
|---|---|
Scan & Library | Phase-aware live scan state, manual scan, thumbnail-only rebuild, and library-index rebuild actions. Admins also see the full report path when a scan finishes with skipped media errors. |
General Settings | App-language selection with instant local switching plus saved app-wide defaults, Home and Reels default feed modes, the default App Folder photo order, nested folder title format, stories and carousel folder modes, excluded-folder rules, feature introductions, migration decisions, and save-and-scan prompts for folder-rule changes. |
Places | Offline GeoNames preparation status plus place-assignment rebuild actions for GPS-tagged photos. |
Security & Access | Admin password, viewer password, public mode, sign-out, and related auth controls. |
System Status | Storage and index state plus last completed scan details, including whether the last run completed with errors. |
In General Settings, the language selector applies immediately in the current browser. That browser-local override is stored locally, and clicking Save changes also stores the selected language as the app-wide default for browsers without their own override. That saved default also reaches the login gate and other pre-auth translated UI on devices that are using the app-wide language. Nested folder title format changes are presentation-only and update without a scan. Env-backed excluded-folder rules are shown read-only and custom rules are saved at runtime. After changing stories mode, carousel mode, or excluded folders, follow the action shown in Scan & Library to update the index. Run a library scan normally, or rebuild the index when the gallery location requires one.
On mobile, Settings uses a dedicated sticky top icon bar instead of the desktop sidebar.
The live scan state stays open-ended during discovery and becomes determinate when later media-processing work has a known total.
Access protection
Settings can optionally enable role-based local access for the app.
That flow supports:
- turning the admin password on
- changing the admin password
- disabling protection again
- enabling or disabling a separate viewer password
- enabling anonymous public browse mode
- rotating the viewer password without knowing the current one
- signing the current browser session out
Current non-admin behavior:
- viewers can browse the library and use shared likes and collections
- anonymous public visitors can browse immediately and use browser-local favorites and collections
viewerandanonymoussessions can elevate throughUnlock admin- non-admin sessions cannot open Settings
- non-admin sessions cannot use Trash, delete actions, scans, or rebuild actions
Rebuild actions
| Action | What changes |
|---|---|
| Scan for changes | Discovers additions, updates, removals, and exclusions without verifying generated media for unchanged assets. In SCAN_MEDIA_ERROR_MODE=skip, supported-media failures are reported, skipped, and the run finishes as completed_with_errors. |
| Scan and repair derivatives | Performs the same discovery and also verifies generated media for unchanged assets. This action also reclaims obsolete video previews for qualifying direct-playback videos. |
| Regenerate Thumbnails | Clears generated thumbnails and video poster images, then rebuilds them from indexed media only. |
| Rebuild Library Index | Clears indexed folders, posts, likes, folder scan state, and scan history, then rescans the active gallery root and reuses matching cached derivatives when possible. In lazy derivative mode it does not pre-generate missing thumbnails or previews. |
Theme, language, and local UI preferences
The startup screen follows your saved light or dark theme and displays a static Foldergram icon while the app loads. If no theme is saved, it follows your system preference.
The interface supports English, Spanish, Chinese, and German. See App language for language selection and how browser preferences interact with the app-wide default.
The client also persists a few local browser preferences:
- selected language override
- light or dark theme
- whether videos start muted
- last opened folder
- recently opened folders
- recent explore searches
These are stored in localStorage.
The sound control shares one mute preference across the home feed, reels, post viewer, carousels, stories, and shared-post videos. Muting a video keeps subsequent videos muted, including after navigation or a page reload in the same browser. Enabling sound updates that shared preference. If the browser blocks autoplay with sound, use the play control to start the video. Foldergram keeps the chosen sound setting instead of silently muting that video. Sound changes made through native video controls, including mobile fullscreen controls, update the same saved preference.
The selected language also has one extra layer:
- changing the language updates the current browser immediately
- saving
General Settingsstores that language in the app database as the default for browsers without a local override
What is intentionally missing
The current repository does not implement:
- uploads from the UI
- comments
- messaging
- notifications
- multi-user accounts
- remote multi-user permissions
- cloud sync
- hierarchical album navigation
Carousel posts
Carousel posts combine 2–20 images, animated images, and videos in one feed card and viewer. Arrow buttons, keyboard controls, touch swipes, counters, and dots move between items. The post has one shared caption and one set of like, save, collection, trash, and delete actions; active-item download and file details remain asset-specific. See Carousel Posts.