What Lumware is
I set out to blink a few LEDs. I ended up designing a software family for programmable light strips.
I set out to blink a few LEDs. I ended up designing a family of software. This post tells how a strip of a hundred lights turned into a product idea with three faces.
The context
A NeoPixel strip is a list of RGB LEDs in which every light is individually addressable: you can tell light number 47 to turn orange without touching 46 or 48. Physically it is a flexible ribbon with three wires (power, ground, data) and a tiny microcontroller embedded in every LED.
There are a thousand tutorials that make these strips blink. Almost all of them stop at the same place: an Arduino sketch with a hand-coded animation, a fixed palette, maybe a button. Nice as a proof of concept; not enough as a product.
If I want the strip to display an image or a video — anything not written into the firmware ahead of time — the sketch alone is not enough. The microcontroller has no memory for photos and no way to read them from a disk.
What is missing is a host: a computer that does the heavy lifting (decoding images, resizing them, picking colors for each LED) and ships Arduino only the final result, frame by frame, in real time.
The decision
I split the system into two clear halves:
- Host (Python): reads the media, prepares the frames, packs them, and sends them over USB serial.
- Firmware (Arduino): receives frames, paints them on the strip with the timing that WS281x chips demand, and does nothing else.
That split is the first brand decision. The name Lumware comes from there: lum (light) + ware (software). It is the host. It is not the strip. The strip is hardware from a manufacturer; Lumware is what drives it.
Once host and strip were separated, a second idea showed up: if the host can read images and videos, it can also read sensors (camera, microphone, MIDI), or take the output of a 3D engine like Unity. Three different dataflows, one shared idea: something produces pixels, something paints them.
That is how the family is shaped:
- Lumware (this repo, the flagship):
host → strip. Images, video, and renders end up on the strip. - Lumware Capture:
sensor → host. A camera or a microphone feeds a host that decides what to do with the signal. - Lumware Stage:
unity ↔ strip. Unity sends frames and receives strip events (touch, position) in a bidirectional loop.
Each product lives in its own repository. They share a
brand (the spectrum palette, Geist type) and a
vocabulary (frames, transport, host) — but not code.
Not everything has to live in a monorepo.
Why three repos and not one. A monorepo would force release coupling. Lumware Stage depends on Unity, which has its own cycles; Lumware Capture depends on sensor drivers that change often. The flagship is the most stable, and I don’t want a Unity change to stall its PRs. They share a contract (the binary frame), not an implementation.
What Lumware is not
To be explicit:
- Not home automation. Lumware drives the strip, not the room.
- Not mood-lighting. Every value is measured, not vibes-based.
- Not a cloud service. Everything runs on the LAN — no servers, no telemetry.
- Not hardware-bound. The
virtualtransport boots without an Arduino: frames go straight to the dashboard canvas.
What comes next
The next post explains how a 200-line script becomes a product with structure, brand, and a paper trail. The invisible piece that let the idea of a family exist: having it work is not enough — you have to be able to tell the story. What changed the day I decided to treat the code as a product instead of a proof?