Creator of Tesserae, an open-source platform for e-paper dashboards. I build Python backends, embedded firmware, native macOS applications, and developer tooling.
Melbourne, Australia · Ex-ANZ (platform engineering & automation) · Open to full-stack, platform, and embedded-adjacent roles.
dmello.io · LinkedIn · dmellok@icloud.com
tesserae.ink · Documentation · Source
A self-hosted dashboard server for e-ink displays. Compose tile-based dashboards in the browser; the server renders them headless, dithers against each panel's measured colour palette, packs the frame into the panel's native byte format, and delivers it over REST (battery clients) or MQTT (always-on clients). One server drives a fleet of panels: Raspberry Pi, ESP32, Kindle, e-readers, TRMNL-compatible, with 14 panels verified on real hardware.
AGPL-3.0-or-later. No account, no hosted server, you run it.
browser editor Tesserae server panels
┌──────────┐ HTTP ┌──────────────────────┐ MQTT push ┌─────────────┐
│ composer │─────────▶│ headless render │────────────▶│ Pi + Inky │
│ /compose │ │ dither (measured │ ├─────────────┤
└──────────┘ │ palettes) │ REST pull │ ESP32, │
│ pack panel-native │◀───────────▶│ Kindle, │
│ schedule / rotate │ │ TRMNL │
└──────────────────────┘ └─────────────┘
What makes it interesting
- Render once, correctly. The editor preview and the production render load the same URL in headless Chromium, so a dashboard can't look right in the editor and break on the panel.
- Dumb firmware by design. Devices do no on-device image decoding; the server ships exact panel-native bytes (packed Spectra 6, 1-bit mono, 4-bit grayscale). Supporting a new panel is a board header plus one driver.
- Everything is a plugin. Widgets, themes, fonts, renderers, transports, and device kinds are drop-a-folder extension points, and the seams are real directories in the repo.
- Allowlisted widget egress. Widgets declare the network hosts they need; the host enforces the allowlist at the socket layer and an undeclared connection raises rather than phoning home. That is the extent of the containment: widgets run in-process, and the trust boundary is PR review of the audited, sha256-pinned catalog. The threat model is documented, including what it doesn't catch.
- Battery-first device protocol. ESP32 clients wake,
GETtheir frame withIf-None-Match(a 304 skips the download and the slow e-ink refresh), report telemetry, and deep-sleep on a server-driven interval. Wall-clock time comes from the HTTPDateheader, so there's no SNTP on-device. - Signed over-the-air firmware updates. Ed25519-signed release descriptors served from R2 behind a Cloudflare signing Worker, with a capability handshake so a device only takes an update it can verify and apply.
- Panels off the LAN, without a VPN. An optional zero-knowledge relay lets a panel reach its server from anywhere; frames are opaque to the relay, which stores a mailbox and nothing else.
- A documented client contract, not just a client. The device protocol and a scoped Companion API are versioned and fixture-tested, so third-party clients build against them: the community iOS app is written by someone else against that contract.
- Real installation paths. Docker, Home Assistant App, LXC/Proxmox, shell installer, and ESP32 boards flash straight from the browser at tesserae.ink/flash, no toolchain.
Pre-1.0 and moving fast: 3,300+ tests behind an 80% coverage gate, ruff, and mypy (strict on the render and push pipeline modules) on every push. Every release is documented in the changelog.
Tesserae is split into focused repositories, each owning one layer:
| Layer | Repository | What it does |
|---|---|---|
| Core platform | tesserae | Server: editor, render pipeline, scheduler, plugin loader, REST + MQTT transports, docs |
| Device firmware | tesserae-device-firmware | One ESP-IDF codebase driving eight e-paper boards (Seeed reTerminal E-Series, XIAO, Waveshare, TRMNL DIY), flashable from the browser |
| Raspberry Pi clients | tesserae-device-pi-png · tesserae-device-pi-bin | Daemons that paint frames onto Pimoroni Inky panels: a PNG path for the broadest hardware support, a packed-binary path for speed |
| Microcontroller client | tesserae-device-pico-bin | RP2350 deep-sleep client for Inky panels, written in C against the Pico SDK |
| Standalone firmwares | esp32-bin · esp32-bw · photopainter-7.3-bin · CrossInk | Per-panel ESP32 clients, plus a fork of uxjulia/CrossInk that paints a dashboard as an Xteink e-reader's sleep screen |
| BLE tags | tesserae-opendisplay | Bridge that pushes rendered frames to OpenDisplay BLE e-paper tags |
| Widget catalog | tesserae-widgets | Community widgets: pinned release tarballs, sha256-verified, schema-validated, PR-reviewed |
| Widget tooling | tesserae-studio · tesserae-mcp | Authoring IDE with live and faithful preview plus a linter, and an MCP bridge so an agent can build a dashboard and check its own work |
| Public API | tesserae-api | api.tesserae.ink: update checks, catalog metadata, the template index |
| Home Assistant | homeassistant-tesserae-addon | Supervisor App: Tesserae in the HA sidebar, authenticated through HA's own session |
Plus roughly thirty widget repositories, each a self-contained plugin published through the catalog.
Clients written and maintained by other people, against the same documented protocol: a generic CircuitPython client by @bablokb, a PicPak 4.2" client by @varanu5, and an iOS companion app by @charmmmz.
i3-like tiling window manager for macOS. A GPL-3.0 fork of nikitabobko/AeroSpace adding a tabbed layout with Liquid Glass tab bars, drag-and-drop between tabs, wallpaper theming, i3-style floating, and i3-compatible splitting. Swift, against the macOS Accessibility APIs.
Native macOS menu-bar app showing live Claude Code usage: 5-hour and 7-day windows, per-model breakdowns, and extra-usage credits, with reset countdowns in the menu bar. Built because usage limits are invisible until you hit them. Swift/SwiftUI, reads OAuth tokens from the Keychain (with refresh handling), and includes a zero-dependency MQTT 3.1.1 publisher on Apple's Network framework for Home Assistant dashboards.
Self-hosted personal finance dashboard for Australian bank and brokerage accounts via the Consumer Data Right. Built because personal financial data shouldn't live in someone else's cloud. FastAPI + SQLModel/SQLite with an in-process scheduler; the async sync client is rate-limit aware and idempotent (watermarks + merge on provider ID); money is Decimal end-to-end; six tabs of ECharts visualisations with no frontend build step. mypy --strict and pytest in CI.
Custom firmware for a 256×50 vacuum-fluorescent display driven by a Raspberry Pi Pico W: eleven pages of live info (weather, now-playing with audio visualisers, 3D-print progress, Claude usage) fed over MQTT. Required a custom u8g2 fork, since the GP1287BI controller isn't upstream and the panel needs LSB-first software SPI on a non-SCK pin. OTA updates, a wireless screenshot endpoint, and Home Assistant presence/lux integration. Build writeup.
Thin vector-rendering client rewrite of the SCTV Scope Clock firmware (Teensy 3.6 driving a CRT) with an ESP32-S3 Wi-Fi bridge. GPL-2.0-or-later, derived from nixiebunny/SCTVcode.
Backend — Python, Flask, FastAPI, SQLModel, SQLite, Playwright, pytest, ruff, mypy (strict)
Frontend — TypeScript, Lit, vanilla JS, Chart.js, ECharts, Astro, server-rendered HTML/CSS
Embedded — C, C++, ESP-IDF, Pico SDK, PlatformIO, ESP32-S3, RP2040/RP2350, e-paper and VFD drivers
Native — Swift, SwiftUI, Keychain, Network framework, menu-bar apps
Infrastructure — Docker, GitHub Actions, Cloudflare Workers/R2, MQTT, Home Assistant, REST/OpenAPI, OAuth, systemd
- Extending the Companion API so community clients can drive more of the server: the photo library shipped, offline album authoring is next
- Improving the render pipeline: palette calibration, dithering quality, panel-native formats
- Widening real-hardware coverage, and getting every listed panel confirmed rather than assumed
- Growing the community widget catalog and its review tooling
- Keeping the documentation ahead of the code
If Tesserae earns a place on your wall, sponsorship keeps the panels lit. For everything else: dmello.io · LinkedIn ·





