Frambe

Frambe

A lightweight, self-contained Docker web application that connects to your Immich server and displays photos in a beautiful full-screen slideshow — perfect for turning old tablets, spare screens, and Raspberry Pis into digital photo frames.

Features

  • Immich API Integration — Connects securely via API key (kept server-side)
  • Album Browser — Select any album (owned or shared), random photos, or favorites only
  • Person / Face Support — Display photos of a specific person via Immich's face recognition
  • Admin Dashboard — Real-time WebSocket-based control panel for all connected frames
  • Admin Authentication — Optional username/password login to protect the admin dashboard
  • REST API with Token Auth — Control frames from Home Assistant, scripts, or external tools
  • URL-Based Zero-Touch Launch — Skip the setup screen entirely with query parameters
  • Auto-Refresh — Periodically checks for new photos added to the source album/person
  • Smooth Crossfade — Double-buffered image transitions with configurable duration
  • Background Blur — Blurred backdrop fills the space behind non-covering images
  • Clock & Date Overlay — Always know the time at a glance
  • EXIF Info — Shows photo location, date, and camera info
  • Progress Bar — Subtle indicator of time until next photo
  • Touch Controls — Tap left/right edges to navigate, centre to toggle overlay
  • Keyboard Controls — Arrow keys, Space, F (fullscreen), I (info), Esc (exit)
  • Screen Wake Lock — Prevents screen sleep on supported devices
  • Responsive — Works on any screen size from phone to TV
  • Older Device Friendly — Vanilla HTML/CSS/JS, no heavy frameworks
  • Docker Containerised — Single container, minimal footprint

🚀 Deployment

Prerequisites

  • A running Immich server
  • An Immich API key (see below)
  • Docker and Docker Compose (recommended) — or Node.js 18+ for running from source

1. Get your Immich API Key

  1. Open your Immich web interface
  2. Click your profile picture → Account SettingsAPI Keys
  3. Create a new key with asset.read and album.read permissions
  4. Copy the key — you'll need it for the next step
git clone https://gitea.hideawaygaming.com.au/jessikitty/frambe.git
cd frambe

Edit docker-compose.yml and set your IMMICH_URL and IMMICH_API_KEY:

environment:
  - IMMICH_URL=http://your-immich-server:2283
  - IMMICH_API_KEY=your-api-key-here

Then start the container:

docker compose up -d

Frambe is now running at http://your-server:3030.

3. Deploy with Docker Run

If you prefer not to use Compose:

docker build -t frambe .
docker run -d \
  --name frambe \
  -p 3030:3000 \
  -e IMMICH_URL=http://your-immich-server:2283 \
  -e IMMICH_API_KEY=your-api-key \
  --restart unless-stopped \
  frambe

4. Run from Source (development)

git clone https://gitea.hideawaygaming.com.au/jessikitty/frambe.git
cd frambe
npm install

Create a .env file from the example:

cp .env.example .env

Edit .env with your Immich URL and API key, then start the server:

npm start

Frambe will be available at http://localhost:3000.

Port Mapping

The internal server runs on port 3000. The Docker Compose config maps this to external port 3030 by default. You can change this in docker-compose.yml:

ports:
  - "8080:3000"    # Access Frambe on port 8080 instead

🔄 Upgrading

cd frambe
git pull
docker compose build
docker compose up -d

Your configuration in docker-compose.yml is preserved — only the application code is rebuilt.

Docker Run

cd frambe
git pull
docker stop frambe
docker rm frambe
docker build -t frambe .
docker run -d \
  --name frambe \
  -p 3030:3000 \
  -e IMMICH_URL=http://your-immich-server:2283 \
  -e IMMICH_API_KEY=your-api-key \
  --restart unless-stopped \
  frambe

From Source

cd frambe
git pull
npm install
npm start

Switching to a Specific Version

Frambe uses git tags for releases. To pin to a specific version:

git fetch --tags
git checkout v1.4.1        # Replace with desired version
docker compose build && docker compose up -d

To switch back to the latest:

git checkout main
git pull
docker compose build && docker compose up -d

Upgrade Notes

  • All upgrades are non-destructive — Frambe stores no persistent data on disk. All configuration is via environment variables.
  • No database migrations — there is no database. Session tokens are in-memory and will reset on restart (users simply log in again).
  • Check the changelog below before upgrading major versions for any new required environment variables.

🔑 Authentication

Admin Dashboard Login

Protect the admin dashboard with a username and password:

environment:
  - ADMIN_USERNAME=admin
  - ADMIN_PASSWORD=your-secure-password

When ADMIN_PASSWORD is set, accessing /admin requires signing in. When not set, the dashboard is open (useful for trusted local networks).

API Token for External Access

Enable token-authenticated REST API access for Home Assistant, scripts, or other external tools:

environment:
  - FRAMBE_API_TOKEN=your-secret-token-here

🔌 REST API

When FRAMBE_API_TOKEN is configured, the following endpoints are available:

List Connected Frames

GET /api/clients
Authorization: Bearer your-secret-token-here

Returns all connected frame clients with their status, IP, name, and config.

Send Command to a Frame

POST /api/clients/:id/command
Authorization: Bearer your-secret-token-here
Content-Type: application/json

{
  "action": "next",
  "payload": {}
}

Available actions: start, stop, next, prev, sleep, wake, refresh, setSource, setConfig

Home Assistant Example

rest_command:
  frambe_next_photo:
    url: "http://frambe-server:3030/api/clients/{{ client_id }}/command"
    method: POST
    headers:
      Authorization: "Bearer your-secret-token-here"
      Content-Type: "application/json"
    payload: '{"action": "next"}'

Authentication can also be provided via x-api-token header or ?token= query parameter.


🔗 Zero-Touch URL Parameters

Skip the setup screen entirely by passing query parameters. This is ideal for dedicated frames — just bookmark the URL on each tablet:

URL What it shows
http://server:3030/?album=ALBUM_UUID Photos from a specific album
http://server:3030/?person=PERSON_UUID Photos of a specific person (face recognition)
http://server:3030/?favorites Favorite photos only
http://server:3030/?random Random photos from the library

You can find album and person UUIDs in Immich's web interface URL bar when viewing an album or person.


⚙️ Configuration

All settings are via environment variables. Set them in docker-compose.yml, pass with docker run -e, or put them in a .env file when running from source.

Variable Default Description
IMMICH_URL (required) Your Immich server URL
IMMICH_API_KEY (required) Immich API key
SLIDESHOW_INTERVAL 30 Seconds between photos
TRANSITION_DURATION 2 Crossfade duration in seconds
IMAGE_FIT contain contain or cover
SHUFFLE true Randomise photo order
BACKGROUND_BLUR true Show blurred backdrop
SHOW_CLOCK true Display clock overlay
SHOW_DATE true Display date overlay
SHOW_EXIF true Display photo metadata
SHOW_PROGRESS true Display progress bar
INCLUDE_VIDEOS true Include video assets in slideshow
REFRESH_INTERVAL 300 Seconds between source refresh checks (new photos)
ALBUM_ID (empty) Auto-start with specific album (env-based)
SHOW_FAVORITES_ONLY false Auto-start with favorites (env-based)
ADMIN_USERNAME admin Admin dashboard login username
ADMIN_PASSWORD (empty) Admin dashboard password (leave empty to disable auth)
FRAMBE_API_TOKEN (empty) API token for REST endpoint access (leave empty for open access)
PORT 3000 Internal server port (Docker maps externally via compose)

🎮 Controls

Touch / Mouse

  • Left 20% of screen — Previous photo
  • Centre 60% — Toggle overlay (clock, info, close button)
  • Right 20% — Next photo

Keyboard

  • / — Previous / Next photo
  • Space — Next photo
  • F — Toggle fullscreen
  • I — Toggle info overlay
  • Esc — Exit to album selection

📱 Tablet Setup Tips

  1. Open the frame URL in your tablet's browser (use a ?album= or ?person= URL for zero-touch)
  2. Add to Home Screen for a full-screen app experience
  3. Enable kiosk mode or guided access to lock to the app
  4. Disable screen timeout in your device settings

🏗️ Architecture

┌──────────────┐         ┌──────────────┐         ┌──────────────┐
│   Browser    │  HTTP   │    Frambe    │   API   │    Immich     │
│  (Tablet)    │◄────────►│  (Node.js)  │◄────────►│   Server     │
└──────────────┘  :3030  └──────────────┘  :2283  └──────────────┘
                              ▲
                    ┌─────────┴─────────┐
                    │  REST API / WS    │
                    │  (Home Assistant) │
                    └───────────────────┘

The Node.js backend acts as a secure proxy — your Immich API key never reaches the browser. The frontend periodically polls the backend for new photos so albums stay up to date without restarting.


🏷️ Versioning

Frambe follows Semantic Versioning:

  • Major (X.0.0) — Large feature overhauls, breaking changes, or major UI redesigns
  • Minor (0.X.0) — New features, functionality additions, or significant improvements
  • Patch (0.0.X) — Bug fixes, small tweaks, and minor corrections

Branches

Branch Purpose
main Stable releases — production-ready code
dev Development — latest features, may be unstable

Changelog

v1.4.1 — Shared Albums

  • Album picker now shows shared albums alongside owned albums
  • Shared albums are visually marked with a "Shared" badge in the picker
  • Shared album icons use 🔗 to distinguish from owned 📁 albums
  • Deduplication ensures albums shared with yourself don't appear twice

v1.4.0 — Admin Auth & REST API

  • Admin dashboard login with username/password authentication (env-based)
  • Session management with HttpOnly cookies (24-hour expiry, automatic cleanup)
  • API token authentication for external access (Home Assistant, scripts, curl)
  • REST endpoint: GET /api/clients — list all connected frames
  • REST endpoint: POST /api/clients/:id/command — send commands to frames
  • Multiple auth methods: Bearer token, x-api-token header, ?token= query param
  • Auth status endpoint: GET /api/auth/status
  • Backwards compatible — auth is opt-in, disabled by default
  • 🆕 New env vars: ADMIN_USERNAME, ADMIN_PASSWORD, FRAMBE_API_TOKEN

v1.3.0 — Admin Dashboard & Video Support

  • Real-time admin dashboard at /admin with WebSocket communication
  • Live frame management: start, stop, next, prev, sleep, wake, refresh
  • Remote source switching: change album, person, random, or favorites per frame
  • Remote config: adjust slideshow interval, toggle clock/date/EXIF/progress per frame
  • Frame naming and rename support (persists by IP)
  • Video playback support in slideshow (with INCLUDE_VIDEOS toggle)
  • Person / face recognition photo source via Immich's people API
  • Connection status indicators and auto-reconnect

v1.2.1 — Bug Fixes

  • 🐛 Fixed port mapping (3030:3000 external:internal)
  • 🐛 Fixed URL parameter auto-launch not starting the slideshow

v1.2.0 — Zero-Touch Launch & Auto-Refresh

  • URL query parameters for zero-touch launch (?album=, ?person=, ?favorites, ?random)
  • Person / face support — display photos of a specific person
  • Periodic auto-refresh — new photos appear without restarting
  • App icon for home screen bookmarks
  • Default external port changed to 3030
  • 🆕 New env var: REFRESH_INTERVAL

v1.1.0 — Rebrand

  • Rebranded to Frambe

v1.0.0 — Initial Release

  • Album browser with Immich API integration
  • Full-screen slideshow with smooth crossfade transitions
  • Double-buffered image loading for seamless display
  • Background blur behind non-covering images
  • Clock, date, and EXIF metadata overlays
  • Progress bar showing time until next photo
  • Touch controls (left/centre/right tap zones)
  • Keyboard controls (arrows, space, F, I, Esc)
  • Screen wake lock to prevent display sleep
  • Configurable via environment variables
  • Docker containerised deployment
  • Vanilla HTML/CSS/JS frontend — no frameworks, works on older devices

📄 License

MIT

S
Description
A lightweight Docker web app that connects to Immich API and displays photos as a digital photo frame — perfect for old tablets and spare screens
Readme MIT 474 KiB
Languages
HTML 53.5%
JavaScript 32.6%
CSS 12.8%
Dockerfile 1.1%