Under the hood

Built with ScrollKit

Theme Park Waits is a thin domain app on top of ScrollKit, an open-source LED-matrix library for what comes after the scrolling “Hello, World.” Over-the-air updates to boards in the field, fault-tolerant data refresh, real transitions and effects, and a web server users control from a browser: all running at once on a microcontroller without the display stuttering.

Want to tinker rather than read internals? Start with Make It Yours: change ride art, preview it in the simulator, and flash your own version.

The hard part isn’t any one feature

It’s running all of them at once on a board with a few hundred kilobytes of RAM, and keeping the panel smooth while a 90 KB network fetch is in flight. ScrollKit provides the whole stack the app builds on:

Display abstraction

One API drives the real HUB75 panel and a desktop simulator from the same code.

WiFi, HTTP & settings

Connection management, a resilient HTTP client, and persisted settings.

Config web server

The browser configuration page the sign hosts itself. No app, no account.

Over-the-air updates

Version-checked updates from a public GitHub channel, applied on-device.

Effects & transitions

A dozen image animators, thirteen transitions, and text/number effects.

Desktop simulator

A pygame emulator that runs the identical render pipeline, and exports its own GIFs and videos.

Engineered to survive the real world

A sign on a shelf has to recover from trouble with nobody watching. 3.0’s reliability isn’t one feature. It’s layers, each catching a different failure:

A hardware watchdog for the frozen case

An opt-in hardware watchdog (default 8 second timeout) is fed from the display loop like a heartbeat. If the loop wedges (a hung synchronous fetch, say) the board resets itself and recovers instead of sitting frozen until someone pulls the plug. It even disables itself while a USB serial console is attached, so it won’t reboot mid-debug. Hardware-validated on CircuitPython 9.2.7 and 10.2.1.

A last-resort reboot for the “everything fails” case

The watchdog only catches a frozen loop. A separate mechanism tracks a streak of consecutive failed fetches and, after enough of them, reboots to clear a wedged radio or session. It was written for a real field failure: one box logged 637 failed fetches over ~2 days and never self-recovered. It does now.

A safe-mode breaker so you’re never locked out

If fault-reboots start stacking up with no healthy run in between, a reboot-loop breaker (backed by non-volatile memory) stops the fetching, shows “Safe mode: reconfigure,” and keeps the configuration page reachable. Paired with self-healing WiFi reconnection and a low-memory floor that refuses to serve stale data, the sign heals from a power blip on its own.

The honest version of the timeline: those last two safeguards exist because 2.x boxes in the wild found the failure modes first. 3.0 is what shipping to fifty people for a few years teaches you.

The fun layer

An effect engine, randomized at runtime

Twelve per-frame image animators (twinkle, motion, emitter, orbit, split-flap, and more), thirteen named screen transitions, and gradient/particle text effects. The app queries ScrollKit’s live effect catalog and randomizes per screen, so the motion varies instead of looping.

See the effects in motion →

Meta note

Every animated clip on this site (the hero, the ride icons, the transitions) was rendered by ScrollKit’s own desktop simulator, running the exact CircuitPython code. No mockups.

Runs on more than one board

The domain app, effects, transitions, web server, and OTA are all board-agnostic. A board only differs in how the panel is constructed, its geometry, and a calibrated performance profile.

  • Adafruit Matrix Portal S3 (ESP32-S3): the default, calibrated from a real device.
  • Pimoroni Interstate 75 W (RP2350): supported.
  • Desktop (macOS / Linux / Windows): the pygame simulator, no hardware required.

How it was built

ScrollKit and Theme Park Waits were built with heavy use of AI-assisted, spec-driven development (Claude Code), directed and reviewed by the author. Both things are true at once: the reliability engineering is real and hard-won from years of shipping a physical product to real customers. And modern tooling is what made a one-person, ground-up 3.0 rewrite feasible.

Read the ScrollKit docs Theme Park Waits on GitHub

ScrollKit and Theme Park Waits are both open source under the MIT license.

Build the thing this powers

Four parts, no soldering, about $80. The full guide is a click away.

Build your own →