Tesserae: a self-hosted render and push server for e-ink dashboards
E-ink dashboard companion. Compose dashboards in a browser, render server-side, and push to e-ink panels over REST or MQTT.
At a glance
- What is it?
- Tesserae separates dashboard composition from rendering: you build tile layouts in a browser, the Python server rasterises them headless, and panels receive finished frames over MQTT or HTTP. The design is sound for mixed fleets, but the AGPL licence and the fast release cadence are the two things to weigh before adopting it.
- Who is it for?
- Adopt Tesserae if you already run Home Assistant or similar and want one server driving several e-ink panels of different sizes, and if AGPL-3.0 is acceptable for how you deploy it. Do not adopt it if your panels are locked to a vendor cloud, if you need a hosted service with an SLA, or if you cannot run a Python service that you patch on the project's release schedule.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Tesserae targets: many panels, one source of truth
Most e-ink dashboard projects assume one screen. You write a script, it draws a frame, it posts the frame to one device, and the script knows the panel's resolution and colour capability. That breaks the moment you add a second panel with a different size or a different display technology. The README's hero image is explicitly nine panels on one server, each running a different dashboard: a GitHub contribution graph, a Home Assistant sensor board, a Hacker News feed with a word clock, a calendar with a Spotify artists panel, a weather and music board, a GitHub stats board, a Kindle Paperwhite, an F1 countdown, and a large weather, climate and battery board. That is the shape of the problem Tesserae is built around. The composition step (what goes on the screen) is decoupled from the delivery step (which panel gets which frame and over what transport). If you have one panel and a cron job, this is more machinery than you need.
Compose in the browser, render headless, push over MQTT or HTTP
The architecture described in the README has three stages. First, tile-based dashboards are composed in a browser, which means the layout is data the server stores, not code you edit per panel. Second, the server renders the frame headless, so no display or compositor is needed on the host and the same layout can be rasterised at whatever resolution a target panel requires. Third, the finished frame is pushed to one or more panels over MQTT or HTTP. The README's summary line is precise about this: compose in a browser, render the frame headless, push it to one or more panels. The transport split matters for deployment. MQTT suits panels that already sit on a broker, which is the common case for ESP32 devices in a home automation setup. HTTP suits panels that expose an endpoint or poll for a frame. The repository topics list esp32, raspberry-pi and home-assistant alongside self-hosted, which is consistent with that reading. What the supplied material does not describe is the renderer itself or the tile schema, so I cannot say how custom widgets are defined beyond the fact that the documentation has a page on building one.
Install surface, outbound traffic and the first-run prompt
The README points to docs.tesserae.ink for install guides and hardware quickstarts rather than embedding commands, so I cannot reproduce a working install line from the material I have. What is stated is that the project is self-hosted, has no SaaS and no cloud account, and that the only outbound contact is api.tesserae.ink, used for update checks, an anonymous install count, and a daily aggregate heartbeat. That traffic is off by default and opt-in. The README says you are asked once at first-run setup, and the toggle lives in Settings → System → Online features. That phrasing gives you the two config touchpoints worth knowing before you deploy: the first-run prompt, and the Online features section under System in Settings. If you run this on a segmented network, expect the first-run prompt to appear before you have decided anything, and know that declining it is the documented default state. The README also links a Codespaces launch badge, which suggests the maintainer supports a browser-based trial path, though the material does not describe what that environment contains.
Where the documentation is thin and where the design costs you
Two gaps stand out. The README is truncated before the widget-building section, so the extension model is only visible as a link. If your dashboards need a data source that is not in the widget gallery, you are relying on that page rather than anything in the repository description. Second, the release cadence is high: v0.392.0, v0.386.3 and v0.386.2 all landed within a few days of each other in September 2026, and the last push to main is dated 2026-09-10. A minor version jumping from 386 to 392 in two days tells you the project is moving quickly, which is good for widget coverage and bad if you pin versions and patch deliberately. The 0.x version number is consistent with that: the maintainer is not claiming interface stability. There is also a real failure mode implied by the architecture rather than stated in the material. Because rendering happens server-side and delivery happens over a network transport, a panel that is offline when a frame is rendered simply misses that frame. The README does not describe retry behaviour, frame queues, or what a panel displays when the server is unreachable, so treat that as unverified and test it against your own hardware.
How Tesserae differs from ESPHome-style panel firmware
The obvious alternative for someone with an ESP32 and an e-ink panel is ESPHome, where the device itself holds the display logic and pulls sensor state from Home Assistant. The difference in approach is where the drawing code lives. With ESPHome, the panel firmware owns the layout, and changing it means reflashing or reconfiguring the device. With Tesserae, the server owns the layout, renders the frame, and the panel is closer to a receiver. That is better when you have several panels and want to change a layout once, and worse when you want a panel that keeps working with no server present. Tesserae's own topics list home-assistant, so it is not positioned as a replacement for that ecosystem; it is a rendering and distribution layer that sits alongside it. If your panels are already running firmware you like and you only need one screen, the ESPHome route keeps one fewer service in the loop.
Licence and the cost of keeping it current
Tesserae is AGPL-3.0-or-later, and the README repeats AGPL-3.0-or-later in its own text. That is a network-copyleft licence. If you modify the server and let users interact with it over a network, the licence's network-use condition is the thing to read, and I am not giving legal advice here: check with someone qualified if you plan to host a modified version for others. For a purely personal or internal deployment where you do not modify and expose the code, the practical effect is usually limited to the obligation to pass on the licence and source when you redistribute. The maintenance cost is the other half. With releases arriving every few days and a 0.x version number, you should expect to read changelogs rather than assume upgrades are drop-in. The README's update-check feature exists precisely because the project expects you to track releases, and it is off by default, so you will not be notified unless you turn on Settings → System → Online features or watch the repository yourself.
Editorial conclusion
Adopt Tesserae if you already run Home Assistant or similar and want one server driving several e-ink panels of different sizes, and if AGPL-3.0 is acceptable for how you deploy it. Do not adopt it if your panels are locked to a vendor cloud, if you need a hosted service with an SLA, or if you cannot run a Python service that you patch on the project's release schedule. Before committing, verify three things: that your exact panel model is covered by the quickstart documentation, what the first-run online-features prompt does on your network, and whether your deployment triggers the AGPL network-use clause.
Community notes