Crema

Crema

Docker app from Florian Dambrine's Repository

Overview

Crema is a small Node.js LAN messenger for always-on displays. It serves a PWA, a display view, settings, history, and logs over HTTP.

Crema

Local LAN messenger between Raspberry Pis on always-on screens. Send a short message from your phone (PWA) or with a one-tap shortcut on the Pi screen itself, and it surfaces on the recipient's Pi. Each message carries its own time-to-live that defines the sender's availability window; the recipient sees a live countdown and can fire back a tap-friendly reply. Each Pi sits in idle as an ambient sage clock with day/night theming, shows who else is online on the LAN, and exposes its configured shortcuts at the bottom of the screen.

Releases: github.com/Aurel-Charles/crema/releases

What works today

  • Symmetric peer-to-peer — identical code on every Pi; add another by flashing the same image and it's discovered automatically.
  • Dual transport (default) — a broker client and the p2p stack run at once: broker primary, direct Pi-to-Pi HTTP as the warm fallback, automatic failover both ways. Pure-p2p and pure-broker modes also exist. See docs/transport.md.
  • mDNS auto-discovery + active health check — Pis (and the broker) find each other on the LAN; each Pi pings every peer's /me every 10 s and drops it after 3 misses, catching reboots and power cuts mDNS goodbyes miss.
  • PWA sender — install http://pi-<name>.local:3000 to your phone, pick a recipient, send.
  • Display kiosk + day/night theme — fullscreen Chromium: clock, date and presence in idle, incoming messages for their TTL; palette shifts at local sunrise/sunset (CREMA_LAT / CREMA_LON).
  • Quick replies & custom response options — tap-friendly reply buttons under each message, configurable per Pi, optionally overridden per-message.
  • TTL + smart defaults — sender picks an availability window (30 s / 5 min / 1 h / Ce soir / Perso…); recipient sees a live il y a Xs · encore Ymin subtitle and a progress bar.
  • Touch shortcuts on the Pi — up to 6 one-tap preset messages on the idle screen, greyed out when the target peer is offline.
  • Do Not Disturb + message queue — DND stacks incoming messages instead of taking over the screen; the queue is capped, preserves arrival times, and drains oldest-first when DND clears.
  • History, read receipts, typing & activity log — every message journaled per-Pi in SQLite; /history shows status (en attente → vu → répondu/expiré) live, the display swaps en ligne for écrit… while a peer types, and /logs is a filterable event timeline.
  • Direction Mirage — a shared sunset visual system (coral accent, Currents rainbow signature) across PWA and display. See docs/architecture.md.
  • Small-screen profile — a dedicated layout for physically tiny panels (e.g. a 3.5" touchscreen). See docs/pi-desk-3.5-screen.md.

Quick start

Task Command
Provision a Pi (recommended) cd ansible && ansible-playbook playbook.yml --ask-become-pass --limit pi-<name> (ansible)
Set up a Pi by hand see docs/setup.md
Update a Pi cd ~/crema && git pull && sudo systemctl restart crema (or ansible-playbook … --tags deploy — restarts the server and reloads the kiosk when the code changed)
Reload the display only pkill -f chromium (the kiosk auto-restarts), or ansible-playbook … --tags reload
Reboot the Pis ansible-playbook … --tags reboot (opt-in, one at a time)
Switch transport ./pin-broker.sh · ./reset-transport.sh · ./disable-broker.sh (transport)
Run the broker relay cd broker && ./install-broker.sh (transport)
Server logs / status sudo journalctl -u crema -f · sudo systemctl status crema
USB Wi-Fi dongle drops ./wifi-watchdog-on.sh (usb-wifi-dongle)

Docs

  • ansible/README.md — one-shot Pi provisioning from the Mac (Node + clone + service + watchdog + broker pin), the recommended setup path.
  • setup.md — install a new Pi, deploy updates, Docker image.
  • transport.md — the three transport modes, switching, running the broker relay.
  • broker-protocol.md — the broker wire protocol (register / deliver / presence).
  • architecture.md — how it's built, tech stack, and the Direction Mirage design system.
  • cheatsheet.md — one-glance reference for the commands that come up most often (restart, deploy, inspect versions, switch transport, stability test…).
  • operations.md — day-to-day operating notes and known gotchas.
  • pi-desk-3.5-screen.md — Waveshare 3.5" HDMI touchscreen setup.
  • usb-wifi-dongle.md — USB Wi-Fi dongle notes and the rtl8xxxu auto-recovery watchdog.

Repo layout

server.js              entrypoint: Express + Socket.IO, page routes, wiring, shutdown
config.js              env, owner derivation, paths, TTL bounds, constants
transport.js           transport selector — picks dual/p2p/broker from CREMA_TRANSPORT
transport-dual.js      composite: broker primary + p2p fallback, presence aggregation (default)
transport-p2p.js       direct Pi↔Pi HTTP (wraps peers.js); retry + .local re-resolution
transport-broker.js    Socket.IO client to the LAN relay
discover-broker.js     mDNS discovery of the broker (_crema-broker._tcp) on the Pi
peers.js               mDNS advertise + browse, peer map, dedup, health check (p2p path)
store.js               atomic JSON persistence for replies, shortcuts, DND + their routes
messaging.js           pendingMessages, send pipeline, /send /shortcut/send /reply /inbox,
                       /read-receipt, /typing, inbound dispatch, msg:status + history:new
db.js                  SQLite history (better-sqlite3, WAL): insert/update/group-by-day
logger.js              structured event log: writes to events table, mirrors to
                       stdout, broadcasts 'event:new' over Socket.IO
public/
  index.html           PWA sender (target / message / response options / TTL / typing)
  settings.html        PWA Préférences (DND toggle + replies + shortcuts editor)
  history.html         PWA history page (grouped by day, live status updates)
  logs.html            PWA activity log (filterable timeline grouped by day, live)
  display.html         Pi kiosk (clock, message, queue, DND moon, replies, shortcuts,
                       presence + typing indicator)
  theme.css            Direction Mirage palette + .crema-label utility (single source of truth)
  manifest.json        PWA manifest
  service-worker.js    minimal SW to enable PWA install
  icon.svg
data/                  per-Pi runtime state (gitignored)
  replies.json         configured quick replies
  shortcuts.json       configured touch shortcuts
  dnd.json             Do Not Disturb flag
  history.db           SQLite message journal (sent + received)
start.sh               wraps `node server.js` with nvm sourcing
start-display.sh       Chromium kiosk launcher with restart loop
install-pi.sh          one-shot Pi setup (systemd + autostart + emoji + blanking + build tools)
pin-broker.sh          transport switch: dual + broker pinned to a URL (p2p fallback kept)
reset-transport.sh     transport switch: back to default dual + broker auto-discovery
disable-broker.sh      transport switch: force pure p2p (mDNS only)
enable-broker.sh       transport switch: force pure broker (debug, no fallback)
ansible/               one-shot provisioning from the Mac (idempotent install-pi.sh equivalent + Node bootstrap)
  playbook.yml         install play + USB Wi-Fi watchdog play
  inventory.ini        the Pis: per-Pi user, screen profile, optional broker pin
  README.md            usage, tags, prerequisites
broker/
  server.js            stateless LAN relay: owner→socket registry + deliver routing + /health
  install-broker.sh    one-shot broker setup on a dedicated box (crema-broker.service)
  start-broker.sh      wraps `node server.js` with nvm sourcing
  test-protocol.mjs    standalone protocol smoke test against a running broker
docs/                  setup, transport, broker protocol, architecture, operations, 3.5" screen

Install Crema on Unraid in a few clicks.

Find Crema in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for Crema Review the template variables and paths Click Install

Download Statistics

2,912
Total Downloads

Related apps

Explore more like this

Explore all

Details

Repository
lowess/crema:latest
Last Updated2026-06-03
First Seen2026-05-21

Runtime arguments

Web UI
http://[IP]:[PORT:3000]
Network
bridge
Privileged
false

Template configuration

Web/PWA PortPorttcp

Port used to access the Crema PWA, display, settings, history, and logs.

Target
3000
Default
3000
Value
3000
Embedded Broker PortPorttcp

Socket.IO broker port. Other Crema peers can connect to ws://unraid-ip:[PORT].

Target
4000
Default
4000
Value
4000
Data DirectoryPathrw

Persistent Crema runtime state: replies, shortcuts, Do Not Disturb state, history database, and event logs.

Target
/app/data
Default
/mnt/user/appdata/crema
Value
/mnt/user/appdata/crema
Owner NameVariable

Display name for this Crema instance. Set a unique owner name for each peer.

Target
CREMA_OWNER
Default
Unraid
Value
Unraid
TransportVariable

Transport mode: broker, dual, or p2p. Broker is recommended for Docker because it avoids .local/mDNS peer resolution.

Target
CREMA_TRANSPORT
Default
broker
Value
broker
Embed BrokerVariable

Start Crema's lightweight broker inside this container.

Target
CREMA_EMBED_BROKER
Default
1
Value
1
Broker URLVariable

Socket.IO broker URL used by this Crema app. Keep ws://127.0.0.1:4000 to use the embedded broker.

Target
CREMA_BROKER_URL
Default
ws://127.0.0.1:4000
Value
ws://127.0.0.1:4000
Advertise Broker via mDNSVariable

Advertise this broker as _crema-broker._tcp via mDNS. Keep 0 for Docker and set other peers to ws://unraid-ip:4000 explicitly.

Target
CREMA_BROKER_ADVERTISE
Default
0
Value
0
Allow P2P with Embedded BrokerVariable

Set to 1 only if you want embedded-broker containers to use dual/p2p mDNS discovery. Keep 0 for Docker.

Target
CREMA_ALLOW_P2P_IN_EMBEDDED_BROKER
Default
0
Value
0
Resolve mDNS AddressesVariable

In p2p/dual mode, prefer IPv4 addresses returned by mDNS over .local hostnames. Set to 0 to use hostname-only mDNS resolution.

Target
CREMA_MDNS_RESOLVE_ADDRESSES
Default
1
Value
1
Broker TokenVariable

Optional shared token. Must match the Crema Broker token when broker authentication is enabled.

Target
CREMA_BROKER_TOKEN
LatitudeVariable

Latitude used for the display day/night theme schedule.

Target
CREMA_LAT
Default
49.8941
Value
49.8941
LongitudeVariable

Longitude used for the display day/night theme schedule.

Target
CREMA_LON
Default
2.2958
Value
2.2958