CB Labs

09 — EMBEDDED · 2026

CubeFeed

An ESP32-S3 desk display that serves its own configuration dashboard off its own flash: no app, no account, no cloud.

Built
A desk display and its firmware, which serves its own setup page.
Stack
ESP32-S3, Arduino C++ (arduino-cli), a PSRAM compositor, a vanilla JavaScript dashboard on flash; the device fetches its own data (Flask backend optional).
State
In use; last firmware change April 2026.

IN USE · UPDATED 2 OCT 2026

Firmware working; last changed April 2026

Carter Barnes · cloud engineer, federal Azure · Contact

Render · Five of CubeFeed's ten themes. Not a photo of the device.

What it is

A desk display that shows whatever you point it at: stocks, weather, crypto, air quality, news, sports, now-playing. A Waveshare ESP32-S3 1.9-inch touch display (170×320) runs the firmware and fetches the data itself; the Flask backend from the first version is now optional.

The difference is that the configuration UI lives on the device. There is no app to install and no cloud account. You open the display's own address and drag cards around.

How it works

Firmware
Arduino C++, compiled with arduino-cli, with a PSRAM compositor: the whole frame is composed off-screen, so the panel never tears.
Cards
Seven renderers behind one card interface: metric, weather, media, time, list, status and alert, each with loading, error, empty and stale states. A new data source means a new fetcher, not a new renderer.
Layouts
Five in the builder: stacked, grid, focused, media, minimal. One resolver pairs each layout's rectangles with its zone names, and both the device and the dashboard preview call it, so they cannot disagree about where a zone is.
Themes
Ten, applied across every layout.
Dashboard
A vanilla JavaScript single-page app on LittleFS, with zero build step.
Sensors
A six-axis IMU for auto-rotate, a battery and buttons. Four full-screen reactive scenes run off tilt and touch; a microphone, a light sensor and a PIR are optional and the scenes degrade without them.

By the numbers

7
card renderers behind one interface
10
themes, applied across every layout
350
theme, layout and renderer combinations, none hand-written
170×320 px
1.9-inch touch panel

What I learned

  1. 01

    Separating what a card is from how it is drawn is what made it scale

    Ten themes by five layouts by seven renderers is 350 combinations, and none are hand-written, because a card is a data shape and a renderer is a function of theme and slot.

  2. 02

    A compositor in PSRAM is worth it on a slow SPI panel

    Drawing straight to the display is simpler and looks bad. Compose off-screen, push once.

  3. 03

    Serving your own config UI removes a product category of problems

    No app, no account, no pairing flow, no cloud outage.

  4. 04

    Zero build step is a feature on a device

    The file on flash is the file I edited. There is no bundler to debug over a serial console.

What went wrong

  1. 01

    The dashboard's edits never reached the device

    Adding or removing a card in the builder, or applying a preset, only changed the page's own state, so neither the display nor the preview showed the change. Each of those actions now pushes the config to the device and refreshes the preview.

  2. 02

    One layout name fell through to the wrong layout

    The resolver sent "stacked" to a different layout whose fixed strips are taller than the 170-pixel screen in landscape, so cards ran off the edge. Every layout is now dispatched by name, and an unknown name falls back to stacked.

Next · 10 / 18The $15 Grill FixA Traeger's display died. A bench rig proved the control board was fine and the panel had failed. A $15 replacement panel fixed it, not a new board.