# tesserae-server **Repository Path**: Rockbase-iot/tesserae-server ## Basic Information - **Project Name**: tesserae-server - **Description**: E-ink dashboard companion. Compose dashboards in a browser, render server-side, and push to e-ink panels over REST or MQTT. - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-28 - **Last Updated**: 2026-10-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Tesserae Server

[![License](https://img.shields.io/badge/license-AGPL--3.0-blue?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2Ij48cmVjdCB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgZmlsbD0ibm9uZSIvPjxsaW5lIHgxPSIxMjgiIHkxPSI0MCIgeDI9IjEyOCIgeTI9IjIxNiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiIvPjxsaW5lIHgxPSIxMDQiIHkxPSIyMTYiIHgyPSIxNTIiIHkyPSIyMTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiLz48bGluZSB4MT0iNTYiIHkxPSI4OCIgeDI9IjIwMCIgeTI9IjU2IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ii8+PHBhdGggZD0iTTI0LDE2OGMwLDE3LjY3LDIwLDI0LDMyLDI0czMyLTYuMzMsMzItMjRMNTYsODhaIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ii8+PHBhdGggZD0iTTE2OCwxMzZjMCwxNy42NywyMCwyNCwzMiwyNHMzMi02LjMzLDMyLTI0TDIwMCw1NloiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiLz48L3N2Zz4=&logoColor=white)](LICENSE) [![Latest release](https://img.shields.io/github/v/release/dmellok/tesserae?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2Ij48cmVjdCB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik00Mi4zNCwxMzguMzRBOCw4LDAsMCwxLDQwLDEzMi42OVY0MGg5Mi42OWE4LDgsMCwwLDEsNS42NSwyLjM0bDk5LjMyLDk5LjMyYTgsOCwwLDAsMSwwLDExLjMxTDE1MywyMzcuNjZhOCw4LDAsMCwxLTExLjMxLDBaIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ii8+PGNpcmNsZSBjeD0iODQiIGN5PSI4NCIgcj0iMTIiLz48L3N2Zz4=&logoColor=white&color=8B5CF6)](https://github.com/dmellok/tesserae/releases/latest) [![CI](https://img.shields.io/github/actions/workflow/status/dmellok/tesserae/ci.yml?branch=main&style=for-the-badge&label=ci&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2Ij48cmVjdCB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgZmlsbD0ibm9uZSIvPjxwb2x5bGluZSBwb2ludHM9Ijg4IDEzNiAxMTIgMTYwIDE2OCAxMDQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiLz48Y2lyY2xlIGN4PSIxMjgiIGN5PSIxMjgiIHI9Ijk2IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ii8+PC9zdmc+&logoColor=white)](https://github.com/dmellok/tesserae/actions/workflows/ci.yml) [![GitHub Discussions](https://img.shields.io/github/discussions/dmellok/tesserae?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2Ij48cmVjdCB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0zMi41LDEzOEE3Miw3MiwwLDEsMSw2MiwxNjcuNWwtMjcuNzYsOC4xNmE4LDgsMCwwLDEtOS45My05LjkzWiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiIvPjxwYXRoIGQ9Ik0xNjMuOTQsODAuMTFBNzIsNzIsMCwwLDEsMjIzLjUsMTg2bDguMTYsMjcuNzZhOCw4LDAsMCwxLTkuOTMsOS45M0wxOTQsMjE1LjVBNzIuMDUsNzIuMDUsMCwwLDEsOTIuMDYsMTc1Ljg5IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ii8+PC9zdmc+&logoColor=white&label=discussions)](https://github.com/dmellok/tesserae/discussions) [![Codespaces](https://img.shields.io/badge/codespaces-launch-24292e?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2Ij48cmVjdCB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xMTIsMjA4SDcyQTU2LDU2LDAsMSwxLDg1LjkyLDk3Ljc0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ii8+PHBvbHlsaW5lIHBvaW50cz0iMTIwIDE2MCAxNTIgMTI4IDE4NCAxNjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiLz48bGluZSB4MT0iMTUyIiB5MT0iMjA4IiB4Mj0iMTUyIiB5Mj0iMTI4IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ii8+PHBhdGggZD0iTTgwLDEyOGE4MCw4MCwwLDEsMSwxMTIsNzMuMzQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiLz48L3N2Zz4=&logoColor=white)](https://codespaces.new/dmellok/tesserae?quickstart=1) [![Sponsor](https://img.shields.io/badge/sponsor-%E2%9D%A4-pink?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2Ij48cmVjdCB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xMjgsMjI0UzI0LDE2OCwyNCwxMDJBNTQsNTQsMCwwLDEsNzgsNDhjMjIuNTksMCw0MS45NCwxMi4zMSw1MCwzMiw4LjA2LTE5LjY5LDI3LjQxLTMyLDUwLTMyYTU0LDU0LDAsMCwxLDU0LDU0QzIzMiwxNjgsMTI4LDIyNCwxMjgsMjI0WiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiIvPjwvc3ZnPg==&logoColor=white)](https://github.com/sponsors/dmellok)

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. The self-hosted server needs no account and never has to talk to us: 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). [Tesserae Cloud](https://cloud.tesserae.ink/) is a separate hosted Tesserae for people who would rather not run a server: sign in, create a dashboard, and connect your display. This self-hosted server stays the full product and stays free, and a supported panel is not tied to the cloud: it can be pointed at a server of your own at any time, though dashboards made in the cloud are specific to it and would need recreating here. **πŸ“– [Full documentation](https://docs.tesserae.ink/):** install guides, [hardware quickstarts](https://docs.tesserae.ink/quickstart/), [widget gallery](https://docs.tesserae.ink/widgets/gallery/), [community catalog](https://tesserae.ink/catalog/), [architecture deep dive](https://docs.tesserae.ink/dev/architecture/), [how to build a widget](https://docs.tesserae.ink/dev/writing-a-widget/), [how to add hardware support](https://docs.tesserae.ink/dev/adding-hardware/). ## Quick start ```sh mkdir tesserae && cd tesserae curl -fsSLO https://raw.githubusercontent.com/dmellok/tesserae/main/docker-compose.yml docker compose up -d ``` Open . First request walks through password setup and the onboarding wizard. Other install paths: [Home Assistant App](https://docs.tesserae.ink/install/home-assistant/), [LXC / Proxmox / MicroCloud](https://docs.tesserae.ink/install/lxc/), [macOS / Linux / Pi shell installer](https://docs.tesserae.ink/install/server/), [Windows PowerShell](https://docs.tesserae.ink/install/server/), [manual venv](https://docs.tesserae.ink/install/server/#manual-install). Server is running? Pick a [hardware quickstart](https://docs.tesserae.ink/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](https://github.com/paperlesspaper/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/`](plugins/) Β· [`renderers/`](renderers/) Β· [`transports/`](transports/) Β· [`devices/`](devices/). **Build dashboards with AI (MCP).** Tesserae exposes an [MCP](https://modelcontextprotocol.io) API so an agent can lay out a freeform dashboard, render a preview to check its work, and push it to a panel. It's on by default; run the [`tesserae-mcp`](https://github.com/dmellok/tesserae-mcp) bridge on your agent's machine (a remote agent needs the token from Settings β†’ System β†’ MCP). See [the docs](https://docs.tesserae.ink/dev/mcp/). ## Design decisions **Server-side rendering, dumb firmware.** The server pre-renders each frame into the exact bytes the panel controller wants; the [device firmware](https://github.com/dmellok/tesserae-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](https://docs.tesserae.ink/dev/publishing-a-widget/) 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](https://github.com/dmellok/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](https://docs.tesserae.ink/compatibility/). > **Some links below are affiliate links.** Seeed product links carry a > Tesserae affiliate tag: buying through one gets you a discount at checkout > and pays a small commission that goes back into the project. Nothing is > listed here because of it, and a panel's βœ… / TBD status means exactly what > it says above. Links without the tag are plain product links. ### Seeed Studio The reTerminal E-Series and XIAO ePaper family run the [Tesserae-native firmware](https://github.com/dmellok/tesserae-device-firmware); flash from the browser in one click at [tesserae.ink/flash](https://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.](docs/screenshots/hero-family.jpg) | Model | Panel | Client | Status | |---|---|---|---| | [reTerminal E1001](https://www.seeedstudio.com/reTerminal-E1001-p-6534.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 7.5" mono, 800Γ—480 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | | [reTerminal E1002](https://www.seeedstudio.com/reTerminal-E1002-p-6533.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 7.3" Spectra 6, 800Γ—480 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | | [reTerminal E1003](https://www.seeedstudio.com/reTerminal-E1003-p-6731.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 10.3" mono, 16-level grey, 1872Γ—1404 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | | [reTerminal E1004](https://www.seeedstudio.com/reTerminal-E1004-p-6692.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 13.3" Spectra 6, 1200Γ—1600 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | | [reTerminal Sticky](https://www.seeedstudio.com/reTerminal-Sticky-p-6861.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 3.97" mono, 4-level grey, 480Γ—800 portrait | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | | [XIAO ePaper EE02](https://www.seeedstudio.com/XIAO-ePaper-DIY-Kit-EE02-for-13-3-Spectratm-6-E-Ink.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 13.3" Spectra 6, 1200Γ—1600 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | | [XIAO ePaper EE03](https://www.seeedstudio.com/XIAO-ePaper-DIY-Kit-EE03-for-10-3-Monochrome-ePaper-Display.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 10.3" mono, 16-level grey, 1872Γ—1404 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | TBD | | [XIAO 7.5" ePaper Panel](https://www.seeedstudio.com/XIAO-7-5-ePaper-Panel-p-6416.html) | 7.5" mono, 800Γ—480 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | TBD | | [TRMNL 7.5" OG DIY Kit](https://www.seeedstudio.com/TRMNL-7-5-Inch-OG-DIY-Kit-p-6481.html?sensecap_affiliate=YcT0R1h&referring_service=link) | 7.5" mono, 800Γ—480 | TRMNL firmware | βœ… via BYOS | ### M5Stack The PaperS3's screen has no controller chip: the ESP32-S3 drives the glass directly and the 16 grey levels come from a waveform table in the firmware rather than from the panel. Greyscale tuning is therefore a firmware change. Partial refresh is not implemented yet, so this panel has no tap echo or on-device touch controls, and its touch digitiser is not wired up. The link goes to M5's documentation rather than their store: M5 have marked the PaperS3 end of life and it is sold out, so this entry is for people who already own one. The original **M5Paper** (pre-S3, classic ESP32-D0WDQ6-V3) drives the same 4.7" glass through an IT8951 controller over SPI, so it reuses the reTerminal E1003's greyscale driver. Also discontinued; this entry is for existing owners. The **PaperMono** (2026, Pro and Lite) is a 3.97" 480x800 4-level greyscale handheld on the reTerminal Sticky's controller family, so it reuses that driver and wire format; its panel rails sit behind an I2C IO expander and its battery is read from the on-board PMIC. Confirmed on hardware; touch, microSD and the frontlight are not wired yet. | Model | Panel | Client | Status | |---|---|---|---| | [M5Paper](https://docs.m5stack.com/en/core/m5paper) | 4.7" mono, 16-level grey, 960Γ—540 (IT8951) | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | | [PaperS3](https://docs.m5stack.com/en/core/PaperS3) | 4.7" mono, 16-level grey, 960Γ—540 | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | TBD | | [PaperMono / PaperMono Lite](https://docs.m5stack.com/en/core/PaperMono) | 3.97" mono, 4-level grey, 480Γ—800 portrait (SSD1677) | [tesserae-device-firmware](https://github.com/dmellok/tesserae-device-firmware) | βœ… | ### Pimoroni Inky | Panel | Resolution | Client | Status | |---|---|---|---| | [Inky Impression 4"](https://shop.pimoroni.com/products/inky-impression) (6-colour Spectra 6) | 600Γ—400 | [pi-png](https://github.com/dmellok/tesserae-device-pi-png) or [pi-bin](https://github.com/dmellok/tesserae-device-pi-bin) | βœ… | | Inky Impression 4" (legacy 7-colour ACeP) | 640Γ—400 | [pi-png](https://github.com/dmellok/tesserae-device-pi-png) or [pi-bin](https://github.com/dmellok/tesserae-device-pi-bin) | βœ… | | [Inky Impression 5.7"](https://shop.pimoroni.com/products/inky-impression-5-7) (7-colour ACeP) | 600Γ—448 | [pi-png](https://github.com/dmellok/tesserae-device-pi-png) or [pi-bin](https://github.com/dmellok/tesserae-device-pi-bin) | βœ… | | [Inky Impression 7.3"](https://shop.pimoroni.com/products/inky-impression?variant=55186435244411) (6-colour Spectra 6) | 800Γ—480 | [pi-png](https://github.com/dmellok/tesserae-device-pi-png) or [pi-bin](https://github.com/dmellok/tesserae-device-pi-bin) | βœ… | | [Inky Impression 13.3"](https://shop.pimoroni.com/products/inky-impression?variant=55186435277179) (6-colour Spectra 6) | 1600Γ—1200 | [pi-png](https://github.com/dmellok/tesserae-device-pi-png) or [pi-bin](https://github.com/dmellok/tesserae-device-pi-bin) | βœ… | | Inky [pHAT](https://shop.pimoroni.com/products/inky-phat) / [wHAT](https://shop.pimoroni.com/products/inky-what) | various | [pi-png](https://github.com/dmellok/tesserae-device-pi-png) | works via `pi_png` | ### Waveshare | Panel | Resolution | Client | Status | |---|---|---|---| | [Waveshare 13.3" Spectra 6 (ESP32-S3)](https://www.waveshare.com/esp32-s3-epaper-13.3e6.htm) | 1200Γ—1600 | [esp32-bin](https://github.com/dmellok/tesserae-device-esp32-bin) | βœ… | | [Waveshare 7.3" PhotoPainter (ESP32-S3)](https://www.waveshare.com/esp32-s3-photopainter.htm) | 800Γ—480 | [photopainter-7.3-bin](https://github.com/dmellok/tesserae-device-photopainter-7.3-bin) | βœ… | | [Waveshare 4.2" B/W (ESP32)](https://www.waveshare.com/4.2inch-e-paper-module.htm) | 400Γ—300 | [esp32-bw](https://github.com/dmellok/tesserae-device-esp32-bw) | TBD | ### Xteink (e-readers) Xteink's X-series e-readers run [CrossInk](https://github.com/uxjulia/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](https://docs.tesserae.ink/hardware/picpak/) | 400Γ—300 (4-colour BWRY) | [picpak-tesserae-client](https://github.com/varanu5/picpak-tesserae-client) by [@varanu5](https://github.com/varanu5) | βœ… | | [ZecTrix NOTE4C Devkit](https://docs.tesserae.ink/hardware/note4c/) | 400Γ—300 (4-colour BWRY) | [note4c-tesserae-client](https://github.com/varanu5/zectrix-note4c-devkit-tesserae-client) by [@varanu5](https://github.com/varanu5) | βœ… | | [Soldered Inkplate 10](https://soldered.com/products/inkplate-10) | 1200Γ—825 (9.7" 16-level grey) | [tesserae.inkplate](https://github.com/partridgeworks/tesserae.inkplate) by [@partridgeworks](https://github.com/partridgeworks) | βœ… | | [Soldered Inkplate 6COLOR](https://soldered.com/products/inkplate-6color-e-paper-display) | 600Γ—448 (5.85" 7-colour ACeP) | [inkplate-tesserae-driver](https://github.com/ripking/inkplate-tesserae-driver) by [@ripking](https://github.com/ripking) | βœ… | | [Soldered Inkplate 13SPECTRA](https://soldered.com/products/inkplate-13spectra) | 1600Γ—1200 (13.3" Spectra 6) | [inkplate-tesserae-driver](https://github.com/ripking/inkplate-tesserae-driver) by [@ripking](https://github.com/ripking) | βœ… | | [Pimoroni Inky Frame 7.3"](https://shop.pimoroni.com/products/inky-frame-7-3) (7-colour ACeP) | 800Γ—480 | [tesserae.inkyframe](https://github.com/partridgeworks/tesserae.inkyframe) by [@partridgeworks](https://github.com/partridgeworks) | βœ… | | Pimoroni Inky Frame 7.3" (6-colour Spectra 6) | 800Γ—480 | [tesserae.inkyframe](https://github.com/partridgeworks/tesserae.inkyframe) by [@partridgeworks](https://github.com/partridgeworks) | TBD | | [reMarkable 2](https://remarkable.com/products/remarkable-2) | 1404Γ—1872 (10.3" 16-level grey) | [tesserae.remarkable](https://github.com/partridgeworks/tesserae.remarkable) by [@partridgeworks](https://github.com/partridgeworks) | βœ… | | [reMarkable 1](https://remarkable.com) | 1404Γ—1872 (10.3" 16-level grey) | [tesserae.remarkable](https://github.com/partridgeworks/tesserae.remarkable) by [@partridgeworks](https://github.com/partridgeworks) | TBD | | [reMarkable Paper Pro](https://remarkable.com/products/remarkable-paper/pro) | 1620Γ—2160 (11.8" colour) | [tesserae.remarkable](https://github.com/partridgeworks/tesserae.remarkable) by [@partridgeworks](https://github.com/partridgeworks) | TBD | ### Kindle and Kobo (KOReader) E-readers running [KOReader](https://koreader.rocks) with the [Tesserae plugin](https://github.com/dmellok/tesserae-koreader). The plugin pairs with a claim code, decodes 16-level greyscale frames on the reader, and sleeps between refreshes where KOReader exposes the hardware alarm. Kindles need a jailbreak to run KOReader; Kobo does not. | Panel | Resolution | Client | Status | |---|---|---|---| | Kindle Paperwhite 2 (jailbroken) | 758Γ—1024 | [tesserae-koreader](https://github.com/dmellok/tesserae-koreader) | TBD | | Kindle Paperwhite 3/4, Voyage, Basic 4 | 1072Γ—1448 | [tesserae-koreader](https://github.com/dmellok/tesserae-koreader) | TBD | | Kindle Paperwhite 5, Oasis 3, Scribe | 1236Γ—1648, 1264Γ—1680, 1860Γ—2480 | [tesserae-koreader](https://github.com/dmellok/tesserae-koreader) | TBD | | Kobo Clara HD, Libra 2, Sage, Aura | various | [tesserae-koreader](https://github.com/dmellok/tesserae-koreader) | TBD | ### TRMNL-compatible (HTTP pull) Any client implementing the [TRMNL BYOS spec](https://help.trmnl.com/en/articles/12263392-connect-your-device-to-terminus-byos) works against the `trmnl_png` renderer. | Panel | Resolution | Client | Status | |---|---|---|---| | [TRMNL OG](https://shop.trmnl.com/products/trmnl) | 800Γ—480 | TRMNL firmware | TBD via BYOS | | [TRMNL X](https://shop.trmnl.com/products/trmnl-x) | 1872Γ—1404 (10.3") | TRMNL firmware | TBD | | Amazon Kindle Paperwhite 2 (jailbroken) | 758Γ—1024 | [KOReader trmnl-display plugin](https://github.com/koreader/koreader) (1-bit; see the KOReader section above for the Tesserae 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](https://github.com/dmellok/tesserae/discussions/24). Per-client setup walkthroughs (the firmware repos in the Client column): [Install a client](https://docs.tesserae.ink/install/clients/). Full renderer / device-kind compatibility matrix: [Screens & compatibility](https://docs.tesserae.ink/compatibility/). ## Status Pre-1.0 and moving fast. Every release is documented in the [CHANGELOG](CHANGELOG.md). 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](https://docs.tesserae.ink/privacy/). ## Community - **[Discussions](https://github.com/dmellok/tesserae/discussions)** for show-your-dashboard, widget pitches, and install help. - **[Contributing guide](.github/CONTRIBUTING.md)** for dev setup, the three checks (pytest / ruff / mypy), and commit conventions. [Good first issues](https://github.com/dmellok/tesserae/labels/good%20first%20issue). - **[Hardware reports](https://github.com/dmellok/tesserae/issues/new?template=hardware_compat.yml)**: running an unlisted panel? A compat report is a real contribution. - **[Security policy](.github/SECURITY.md)** Β· **[Code of conduct](.github/CODE_OF_CONDUCT.md)** ## 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](https://github.com/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](https://docs.tesserae.ink/credits/), [NOTICES.md](NOTICES.md). ## License AGPL-3.0-or-later, see [LICENSE](LICENSE).