
Show your Plex/Emby/Jellyfin "now playing" card on a cheap ESP32 touch panel (ESPHome + a tiny screenshot sidecar)
There's a slick project called **[Marquee](https://github.com/Jamisonfitz/marquee)\*\* (by Jamisonfitz) that turns a Google Nest Hub into a beautiful "now playing" card for Plex/Emby/Jellyfin — poster, plot, ratings, progress bar, clock.
For those who don't own a Nest Hub, or are moving away from them, or just love ESP projects, I wanted to expand the project to support ESP32 displays. I bought the first, most popular disoplay on Amazon compatible with ESPhome, a **7" Elecrow CrowPanel** (an ESP32-S3 touch screen). So I made it show the *exact same card* using **ESPHome**. It's on my wall now and I wrote it all up so others can build one.
**Repo:** https://github.com/TRusselo/marquee-esp32
### How it works (the whole trick)
The ESP32 is intentionally dumb. All the layout happens on my server:
```
Plex/Emby/Jellyfin → Marquee (renders a web card)
→ marquee-shot (screenshots the card to a JPEG)
→ ESP32 panel downloads the JPEG and shows it full-screen
```
`marquee-shot` is a tiny container that opens Marquee's real card in headless Chromium and serves it at `/card.jpg`. The panel just downloads that image — so it looks **pixel-identical** to the Nest Hub version, and the ESP config stays dead simple (no on-device layout code). It's a decoupled add-on: it never modifies Marquee, so it works against the plain upstream image too.
### What you need
- Elecrow CrowPanel "Basic" 7" (ESP32-S3-WROOM-1-N4R8, 800×480, GT911 touch). Other panels work — just swap the display pins.
- Marquee running on your LAN (Docker; one-click template on Unraid).
- The `marquee-shot` sidecar: `ghcr.io/trusselo/marquee-shot`.
- ESPHome.
### Quick start
Run the sidecar:
docker run -d --name marquee-shot --network host --restart unless-stopped \
-e MARQUEE_URL=http://127.0.0.1:8084 \
-e PANEL_WIDTH=800 -e PANEL_HEIGHT=480 -e SERVE_PORT=8088 \
ghcr.io/trusselo/marquee-shot:latest
Check `http://your-server:8088/card.jpg\`, then flash `marquee-crowpanel-shot.yaml` in ESPHome (set the sidecar IP up top; first flash over USB, then OTA). Play something → card shows up in a few seconds.
It also taps-to-wake + brightens on a new episode, goes full-bright when paused, dims during playback, and turns the backlight fully off when nothing's playing.
### The RGB-panel gotchas I hit (the actually-useful part)
- **Console on UART0** — ESPHome 2026.7 defaults logs to USB-Serial-JTAG, but those pins are this board's touch i2c bus, so the default kills your logs. `logger: hardware_uart: UART0`. (Cost me an evening of "why no logs?")
- **PSRAM mandatory** — 800×480 framebuffer won't fit in internal RAM. `psram: mode: octal`, keep the `CONFIG_SPIRAM_*` flags or a fresh flash hangs at `entry`.
- **LVGL `buffer_size: 5%`** — the 25% default eats the DMA RAM Wi-Fi needs on an RGB panel, so **Wi-Fi silently won't associate**. Looked like a Wi-Fi bug; was really out-of-RAM. (Screenshot mode skips LVGL entirely.)
- **Pin the ESP-IDF version** if Wi-Fi drops with "Association Expired" — recent IDF had a Wi-Fi regression.
- **GT911 touch: polled, no interrupt pin** (reset is behind a GPIO expander; wiring the IRQ crashed boot). Address `0x5D`.
- **Elecrow's docs for this board are wrong in places.** The reference that actually worked: https://www.espboards.dev/blog/esphome-configuring-elecrow-7-inch-display/
All of this is already handled in the repo's YAML — sharing it because it applies to any RGB ESP32-S3 panel.
Big credit to **[Jamisonfitz/marquee](https://github.com/Jamisonfitz/marquee)\*\* for the actual card — go star it. My repo just adds the ESP32 path on top.
Happy to help anyone adapting it to a different panel. Photos welcome if you build one.