Drive large LED installations and DMX fixtures. One source tree drives ESP32, Teensy, Raspberry Pi, macOS, Windows and Linux.
Flash an ESP32 from your browser and see lights in under a minute: open the web installer in Chrome or Edge, plug in your device, and follow it. No toolchain, no recompile. The Getting started guide takes you from a blank board to a running light show.
No hardware handy? The desktop build runs the same UI and effect pipeline on macOS, Windows and Linux, driving fixtures over Art-Net, DDP or E1.31.
If you like projectMM, give it a star, fork it, or open an issue. It helps the project get noticed.
🎨 Plug in, open a browser, see lights. A live 3D preview of every effect, modifier and layout, controllable from the same tab. The interface renders any module from its declared controls.
🎛️ A pipeline you build visually: layouts, then layers of effects and modifiers, then drivers. Every change applies on the next frame, and settings persist across power cycles. Editing a pin map, a strand length or an output protocol on a running device needs no reboot.
🔵 16,384 lights on a classic ESP32, not only on an S3 or P4. Memory adapts from a 16x16 panel up to 128x128, degrading rather than crashing on tight devices.
🧊 Native 3D throughout: 2D and 1D are the cases where a dimension is size 1, so an effect never picks a mode.
💡 DMX and addressable LEDs together: RGB strips, RGBW pixels, par lights and moving heads through one pipeline.
🌐 Industry protocols both ways: send and receive Art-Net, E1.31/sACN and DDP, interoperable with Falcon, Advatek, xLights, Resolume and LedFx.
🔌 Parallel WS2812 output over three ESP32 peripherals: RMT on every chip, the S3's LCD_CAM i80 bus, and the P4's Parlio engine, each with an on-device loopback test that bit-verifies the wire signal.
🎵 Audio-reactive: an I²S microphone drives a 16-band FFT spectrum and sound level.
🏠 Home automation: a device joins Homebridge and any MQTT hub for on/off, brightness and color. See the MQTT module.
📁 On-device file manager: browse and edit the device filesystem from the browser, with drag-drop upload and firmware update over the LAN.
🛡️ Robust to any input: add, delete, replace or reconfigure any module in any order, at any grid size, and the device keeps running. Every crash found becomes a regression test.
Written against ESP-IDF directly with no third-party libraries, and with our own code rather than a fork: why we write our own code. How it is put together: the architecture.
projectMM is one system in nine named parts. Each has a page that owns its detail.
flowchart TB
subgraph device["On the device"]
direction TB
MoonLight["<b>MoonLight</b><br/>layouts, effects,<br/>modifiers, drivers"]
MoonLive["<b>MoonLive</b><br/>scripts compiled<br/>on the device"]
MoonI80["<b>MoonI80</b><br/>parallel WS2812<br/>over DMA"]
MoonCore["<b>MoonCore</b><br/>controls, scheduling,<br/>persistence, platform"]
MoonModule["<b>MoonModule</b><br/>the one building block:<br/>every part below is one"]
MoonBase["<b>MoonBase</b><br/>installs<br/>updates"]
MoonLive --> MoonLight
MoonLight --> MoonI80
MoonLight --> MoonCore
MoonI80 --> MoonCore
MoonCore --> MoonModule
MoonBase -.-> MoonCore
end
MoonInstaller["<b>MoonInstaller</b><br/>flashes a board<br/>from the browser"]
MoonDeck["<b>MoonDeck</b><br/>build, flash, test,<br/>discover"]
MoonCloud["<b>MoonCloud</b><br/>stats, talk,<br/>sync"]
MoonInstaller -->|"USB"| device
MoonDeck -->|"network"| device
device <-->|"opt-in"| MoonCloud
style MoonCore fill:#2d3561,stroke:#7b88c9,color:#fff
style MoonModule fill:#5a3d7a,stroke:#c9a0e0,color:#fff
style MoonLight fill:#3d2d61,stroke:#a07bc9,color:#fff
style MoonLive fill:#3d2d61,stroke:#a07bc9,color:#fff
style MoonI80 fill:#3d2d61,stroke:#a07bc9,color:#fff
style MoonBase fill:#2d3561,stroke:#7b88c9,color:#fff
style MoonCloud fill:#1f4d3d,stroke:#5fb89a,color:#fff
style MoonDeck fill:#4d3d1f,stroke:#c9a95f,color:#fff
style MoonInstaller fill:#4d3d1f,stroke:#c9a95f,color:#fff
The one building block, and the idea the rest of the system is built on. Every effect, modifier, layout, driver and service is a MoonModule: the same base class, the same lifecycle, and controls the module declares itself.
That uniformity pays three times over. The interface renders any module from its declared controls, so a new module needs no UI code. Persistence, live reconfiguration and the REST API work on a module they have never seen. And adding a capability is a new file rather than a new framework, which is why the catalog grows without the core growing with it.
Architecture: MoonModule · Use it: core modules · light modules
The domain-neutral runtime: the module base class, controls, scheduling, persistence, and the platform abstraction. It knows nothing about lights, which is what lets the light domain stay simple on top of it. Everything in the system is a MoonModule with the same lifecycle and declared controls, and that uniformity is why the interface renders any module with no per-module code.
Architecture: MoonCore · MoonModule · Use it: System · Control · Services
The light domain, and the bigger half of the code: light values, layouts, layers, mapping, blending, effects, modifiers and LED drivers. This is what you build a light show from, stacking a layout, then layers of effects and modifiers, then a driver.
Architecture: MoonLight · Use it: Effects · Layouts · Modifiers · Drivers
Scripts compiled to native machine code on the device. Write an effect in the browser, and it runs at the speed of compiled code rather than an interpreter, on ESP32 and on the desktop alike.
Architecture: MoonLive · Use it: MoonLiveEffect · the script language
Our own DMA driver for parallel WS2812 output, one of the backends ParallelLedDriver selects. It adds a streaming ring and 74HCT595 expander support, which is what drives 12,288 lights from a single board.
Architecture: MoonLight drivers · Use it: LED drivers
A small maintenance image in the factory slot that installs updates into one large app slot, instead of spending half the flash on a second copy of the firmware. A power cut mid-update lands back in MoonBase rather than a half-written app.
Architecture: MoonBase · Use it: System modules
The opt-in server side, and the only server a device talks to. Stats reports what people run so development follows real use, Talk is a public message board between devices, and Sync is planned.
Architecture: MoonCloud · Use it: MoonCloud · privacy policy
The browser installer: it picks your device, flashes the matching firmware, and hands the device your WiFi credentials over USB. No serial monitor, no recompile.
Architecture: MoonInstaller · Use it: Web installer · Getting started · source
The developer console: one page that builds, flashes, runs, tests and monitors across every target, and discovers devices on the network.
Architecture: MoonDeck · Use it: MoonDeck · building.md
A full render pipeline (effect, modifier, Art-Net output) on real hardware, at 128x128:
| Device | Lights | FPS |
|---|---|---|
| Desktop | 16,384 | 9,708 |
Olimex esp32 |
16,384 | 11 |
| LOLIN S3 N16R8 | 16,384 | 6 |
Smaller grids run far faster: a classic ESP32 holds over 1,500 FPS at 16x16 and 81 FPS at 64x64. Pick an Ethernet device when frame rate matters, and an S3 when you need PSRAM headroom for large buffers.
Per-grid and per-device tables, free-heap figures, and why WiFi costs what it does: performance.md. The contracts CI enforces on every run live in test/scenarios/*.json.
ESP32: open the web installer in Chrome or Edge (MoonInstaller). It walks you through device, firmware, flashing and network setup.
Desktop: download your build from the releases page, then open http://localhost:8080/. Step by step with screenshots: Installing projectMM on a desktop.
- macOS arm64:
.dmg, drag to Applications. Ad-hoc signed, so right-click and Open the first time. - Windows x64:
-setup.exeinstalls for your user without an admin prompt. Unsigned, so SmartScreen asks once. - Linux x64 and arm64:
.tar.gz, or.debon Debian, Ubuntu and Raspberry Pi OS. The arm64 build covers a Raspberry Pi, a NanoPi and most 64-bit boards.
From source: you need uv, CMake 3.20+ and a C++20 compiler, plus ESP-IDF v6.x for ESP32. Then launch MoonDeck:
uv run moondeck/moondeck.pyOpen http://localhost:8420 to build, run, test, flash and discover devices. Full setup and every target: building.md.
| Document | What's in it |
|---|---|
| Getting started | Blank board to running light show |
| the architecture | How the system is put together |
| building.md | Build and flash for every target |
| moonmodules/ | One page per module: core and light |
| performance.md | Timing and memory per platform |
| testing.md | What the tests cover |
| coding-standards.md | How code here is written |
| documentation-standards.md | How docs here are written |
| CLAUDE.md | Rules, constraints, and the process |
projectMM is built by AI agents under tight human direction. Everything in this repository is authored by agents; the product owner writes none of it directly. What the product owner authors is the process, the architecture, and the module specifications, then decides what to build, reviews every line, runs the hardware tests, and controls every commit and release. Agents write; the product owner thinks.
The roles, the principles and the full process: CLAUDE.md.
This is the current iteration of years of LED and light-system development, and each prior project proved ideas this one builds on:
| Project | Description | Repo |
|---|---|---|
| WLED | Open-source LED firmware (user and contributor since 2021) | Aircoookie/WLED |
| WLED-MoonModules | WLED fork with advanced features | MoonModules/WLED |
| StarLight | Standalone LED firmware | ewowi/StarLight |
| MoonLight | Ground-up build: 60+ effects, memory-optimized mapping, 11 driver types | ewowi/MoonLight |
We built and maintained these, so projectMM rests on our own hands-on experience. Their lessons are distilled in docs/work/past/. We carry the ideas forward and write our own code, crediting by name whoever inspired a feature.
People whose work directly shaped parts of projectMM. We study their thinking with respect and write our own code against our architecture:
- WLED and WLED-MM: projectMM is born out of WLED and takes the usermod idea further, where everything is a module. A projectMM device also acts as a WLED device and talks to WLED devices.
- Frank (softhack007): main author of the WLED-MM audio-reactive usermod. The ideas behind AudioService, including the adaptive noise gate analyzed with his permission, descend from years of collaboration.
- troyhacks: reworked the WLED-MM audio DSP onto Espressif's esp-dsp FFT, the same choice AudioService makes.
- Stefan Petrick: the generative-field vocabulary from Animartrix, FunkyNoise and ColorTrails. Aurora, PolarNoise, Tunnel and Trails sit in that tradition, written on the published algorithms underneath.
- hpwit (Yves Bazin): the clockless I2S, RMT and Parlio driver techniques, and the ESPLiveScript engine behind MoonLive.
- Christophe Gagnier (@Moustachauve): author of the native WLED-Android and WLED-iOS apps, whose source let projectMM devices appear in them.
- The Improv Wi-Fi project: the open serial provisioning standard the web installer uses.
- FastLED: the canonical LED-effects library whose names and models projectMM carries forward (
scale8,sin8, the gradient-palette model, thebeatsin8family) so a contributor recognizes them on sight. The implementations are our own, integer-only and hot-path-tuned. - FPP (Falcon Player): the show player that prompted PanelCardDriver: if a Linux host can feed a wall of HUB75 panels, so can the board already rendering them.
- Tasmota and Mathieu Carbou's MycilaSafeBoot: the safeboot pattern behind MoonBase, our from-scratch minimal take on it.
- Damian Schneider (dedehai): author of the WLED Particle System, whose shape our particle kernel follows in fixed point.
- wladi (myhome-control): designer of the MHC-WLED ESP32-P4 shield, and the source of the pinout details that got its line-in audio working.
projectMM is a community project, shaped by the people who use it:
- Ideas and requests: an effect, a layout, a driver, a fixture you want supported? Open an issue.
- Help build it: pick something from the issues, or propose a module. The process is in CLAUDE.md.
- Test on hardware: run it on your panels and fixtures, and report what works.
- Talk to us: Discord, Reddit, YouTube, GitHub.
See LICENSE.






