Skip to content

Latest commit

Β 

History

1,384 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Tesserae

License Latest release CI GitHub Discussions Codespaces Sponsor

Nine e-ink panels arranged on a wooden dresser, each running a different Tesserae dashboard: a framed GitHub contribution graph, a Home Assistant sensor dashboard with cat litter tracking, a Hacker News feed with a word clock, a monthly calendar with a Spotify top artists panel, a Melbourne weather + music dashboard, a GitHub stats colour dashboard, a Kindle Paperwhite with local weather, a Belgian Grand Prix F1 countdown, and a large framed Melbourne weather + climate + batteries dashboard. A black cat sits on the shelf above, next to a pothos plant.
Nine panels, one Tesserae server.

Self-hosted dashboard companion for e-ink displays. Compose tile-based dashboards in a browser, render the frame headless, push it to one or more panels over MQTT or HTTP.

Open source under AGPL-3.0-or-later. No SaaS, no cloud account. The only outbound contact is api.tesserae.ink for update checks, an anonymous install count, and a daily aggregate heartbeat, off by default and opt-in (you're asked once at first-run setup; toggle in Settings β†’ System β†’ Online features).

πŸ“– Full documentation: install guides, hardware quickstarts, widget gallery, community catalog, architecture deep dive, how to build a widget, how to add hardware support.

Quick start

mkdir tesserae && cd tesserae
curl -fsSLO https://raw.githubusercontent.com/dmellok/tesserae/main/docker-compose.yml
docker compose up -d

Open http://localhost:8765. First request walks through password setup and the onboarding wizard.

Other install paths: Home Assistant App, LXC / Proxmox / MicroCloud, macOS / Linux / Pi shell installer, Windows PowerShell, manual venv.

Server is running? Pick a hardware quickstart to get a panel on the wall.

How it works

Dashboards are plain HTML. The editor preview and the production render load the same URL: a headless Chromium (Playwright) screenshots the composition at panel resolution, so "looked fine in the editor, broke on the panel" is impossible by construction.

The frame then goes through a per-device renderer: Floyd-Steinberg dithering against the panel's measured color palette (Spectra 6 and ACeP panels don't actually produce sRGB primaries; calibrated measurements come from epdoptimize), then packing into the exact byte format the panel wants: packed 4-bit Spectra 6, 1-bit mono, or 4-bit grayscale.

Devices are deliberately thin clients with no on-device image decoding. Always-on clients (a Pi driving an Inky) get frames pushed over MQTT the moment a page changes. Battery clients (ESP32) wake, GET their frame over REST with If-None-Match (a 304 skips both the download and the slow e-ink refresh), POST battery + RSSI telemetry, and deep-sleep on a server-driven interval. Wall-clock time comes from the HTTP Date header, so there's no SNTP on-device.

browser editor          Tesserae server                    panels
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   HTTP   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   MQTT   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ composer │─────────▢│ headless render      │─────────▢│ Pi + Inky   β”‚
β”‚ /compose β”‚          β”‚ dither (measured     β”‚          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚   palettes)          β”‚   REST   β”‚ ESP32,      β”‚
                      β”‚ pack panel-native    │◀────────▢│ Kindle,     β”‚
                      β”‚ schedule / rotate    β”‚          β”‚ TRMNL       β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Every layer is a drop-a-folder plugin: widgets, themes, renderers, transports, and device kinds. The seams are real directories: plugins/ Β· renderers/ Β· transports/ Β· devices/.

Build dashboards with AI (MCP). Tesserae exposes an optional MCP API so an agent can lay out a freeform dashboard, render a preview to check its work, and push it to a panel. Enable it under Settings β†’ System β†’ MCP, then run the tesserae-mcp bridge on your agent's machine. See the docs.

Design decisions

Server-side rendering, dumb firmware. The server pre-renders each frame into the exact bytes the panel controller wants; the device firmware streams them straight to the panel. Adding a new panel is a board header plus one driver. The network, power, and provisioning stack never changes.

Widget network egress is allowlisted. Third-party widgets declare the network hosts they need in a requires: block in plugin.json, and the host enforces the allowlist at the socket layer. An undeclared connection raises CapabilityDenied instead of phoning home. That is the extent of the containment: widgets otherwise run in-process, and the trust model is PR review of the community catalog, not a sandbox. The threat model is documented honestly, including what it doesn't catch.

One server, a fleet of panels. Tesserae splits rendering from transport from hardware, so a single instance drives every panel in the house, each with its own dashboards, schedules, and rotations.

Community widgets install from an audited catalog. Pinned release tarballs, sha256-verified, schema-validated, PR-reviewed: tesserae-widgets.

Supported hardware

Tesserae renders to one of several panel families through drop-a-folder device plugins. In the tables below, βœ… means the panel has been confirmed on real hardware (on my bench or via a community report); TBD means a client and hardware profile ship but nobody has confirmed a frame on the physical panel yet. The per-renderer bench matrix lives at Screens & compatibility.

Seeed Studio

The reTerminal E-Series and XIAO ePaper family run the Tesserae-native firmware; flash from the browser in one click at tesserae.ink/flash (Chrome / Edge, Web Serial, no toolchain). Battery-powered, no assembly required.

A family of Tesserae-driven e-ink displays on a shelf: reTerminal E1004 with a weather dashboard, reTerminal E1002 with a metrics view, XIAO ePaper panels, and a small colour Inky. Cat photobomb optional.

Model Panel Client Status
reTerminal E1001 7.5" mono, 800Γ—480 tesserae-device-firmware βœ…
reTerminal E1002 7.3" Spectra 6, 800Γ—480 tesserae-device-firmware βœ…
reTerminal E1003 10.3" mono, 16-level grey, 1872Γ—1404 tesserae-device-firmware βœ…
reTerminal E1004 13.3" Spectra 6, 1200Γ—1600 tesserae-device-firmware βœ…
XIAO ePaper EE02 13.3" Spectra 6, 1200Γ—1600 tesserae-device-firmware βœ…
XIAO 7.5" ePaper Panel 7.5" mono, 800Γ—480 tesserae-device-firmware TBD
TRMNL 7.5" OG DIY Kit 7.5" mono, 800Γ—480 TRMNL firmware βœ… via BYOS

Pimoroni Inky

Panel Resolution Client Status
Inky Impression 4" (6-colour Spectra 6) 600Γ—400 pi-png or pi-bin βœ…
Inky Impression 4" (legacy 7-colour ACeP) 640Γ—400 pi-png or pi-bin βœ…
Inky Impression 5.7" (7-colour ACeP) 600Γ—448 pi-png or pi-bin βœ…
Inky Impression 7.3" (6-colour Spectra 6) 800Γ—480 pi-png or pi-bin βœ…
Inky Impression 13.3" (6-colour Spectra 6) 1600Γ—1200 pi-png or pi-bin βœ…
Inky pHAT / wHAT various pi-png works via pi_png

Waveshare

Panel Resolution Client Status
Waveshare 13.3" Spectra 6 (ESP32-S3) 1200Γ—1600 esp32-bin βœ…
Waveshare 7.3" PhotoPainter (ESP32-S3) 800Γ—480 photopainter-7.3-bin βœ…
Waveshare 4.2" B/W (ESP32) 400Γ—300 esp32-bw TBD

Xteink (e-readers)

Xteink's X-series e-readers run CrossInk firmware with Tesserae client support: the dashboard becomes the reader's sleep screen, painted on the sleep transition rather than on a timer.

Model Panel Client Status
Xteink X3 (4-level grayscale) 792Γ—528, gray CrossInk βœ…
Xteink X3 (mono) 792Γ—528, mono CrossInk TBD
Xteink X4 800Γ—480, mono CrossInk βœ…
Xteink X4 (4-level grayscale) 800Γ—480, gray CrossInk βœ…
Xteink X4 Pro 800Γ—480, mono CrossInk TBD

Community

Community-authored clients, contributed and maintained by their authors (not in the Tesserae org). Thanks to everyone building these.

Panel Resolution Client Status
PicPak 4.2" BWRY 400Γ—300 (4-colour BWRY) picpak-tesserae-client by @varanu5 βœ…

TRMNL-compatible (HTTP pull)

Any client implementing the TRMNL BYOS spec works against the trmnl_png renderer.

Panel Resolution Client Status
TRMNL OG 800Γ—480 TRMNL firmware TBD via BYOS
TRMNL X 1872Γ—1404 (10.3") TRMNL firmware TBD
Amazon Kindle Paperwhite 2 (jailbroken) 758Γ—1024 KOReader trmnl-display plugin βœ…

Custom panels

Anything else: pick custom in Settings β†’ Panel and set the dimensions. If a client drives your panel, Tesserae can push frames to it. A generic CircuitPython client (400+ boards) is in development; follow discussion #24.

Per-client setup walkthroughs (the firmware repos in the Client column): Install a client. Full renderer / device-kind compatibility matrix: Screens & compatibility.

Status

Pre-1.0 and moving fast. Every release is documented in the CHANGELOG. CI runs pytest (2,400+ tests, 80% coverage gate), ruff, and mypy (strict on the render/push pipeline modules) on every push.

Built with AI assistance (Claude Code). Architecture decisions, code review, hardware testing, and what ships vs. what doesn't are mine. The changelogs document the debugging in the open.

Privacy

Tesserae contacts one first-party endpoint, api.tesserae.ink, for update checks, an anonymous marketplace install count, and a daily aggregate heartbeat (version, platform, deployment kind, device kinds; no exact counts). No accounts, no personal data, no IP addresses stored, no third-party analytics. It is off by default and opt-in: a fresh install asks once at first-run setup, and it's a single switch at Settings β†’ System β†’ Online features. Per-device diagnostics (battery, RSSI, sleep cadence) stay on the box. Privacy.

Community

Why AGPL

The server stays free even when someone runs it as a service: improvements have to stay public. And a dashboard for your home shouldn't report home. No analytics, no accounts, nothing phones out. Don't take the README's word for it; read the source.

Credits

Tesserae stands on generously-licensed open source: Phosphor Icons, Chart.js, 20 typefaces under SIL OFL / Apache 2.0, the TRMNL BYOS protocol, the KOReader trmnl-display plugin, and paperlesspaper/epdoptimize's Spectra 6 + ACeP calibrated palette measurements (also shipped as selectable presets in the Calibration tab under Apache 2.0). Full attribution: Credits, NOTICES.md.

License

AGPL-3.0-or-later, see LICENSE.

About

E-ink dashboard companion. Compose dashboards in a browser, render server-side, and push to e-ink panels over REST or MQTT.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

518 stars

Watchers

5 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages