This is the deep-dive developer guide for building plugins in the
ledmatrix-plugins monorepo.
It's the human-readable companion to the repo's CLAUDE.md
(which is the dense, LLM-facing quick reference).
A plugin is a self-contained Python package that the LEDMatrix core
(ChuckBuilds/LEDMatrix, a separate repo) loads at runtime and renders on an
RGB LED matrix. This repo ships plugin source plus the registry (plugins.json)
that the in-app plugin store reads.
New to plugins? Copy plugins/hello-world/ and read
it top to bottom — it's the minimal working reference every section below points
back to. Then work through these topics in order:
| # | Topic | What it covers |
|---|---|---|
| 1 | Plugin anatomy & lifecycle | Directory layout, BasePlugin, and the six lifecycle methods the core calls |
| 2 | The core API surface | Everything the core hands you: display_manager, cache_manager, font_manager, plugin_manager, config |
| 3 | Advanced features | Dynamic duration, live priority, high-FPS scrolling, and Vegas continuous-scroll |
| 4 | Styling & skins | User-customizable fonts/colors/offsets (customization, x-style-elements) and the x- UI extensions |
| 5 | Adaptive layout | layout_mode classic vs. adaptive, and rendering across matrix sizes |
| 6 | Manifest & config schema | Manifest fields, config_schema.json conventions, and the version workflow |
| 7 | Testing, CI & the registry | Safety harness, module-collision checks, plugins.json, and the CI gates |
These trip up nearly every first plugin. Each is expanded in the topic pages:
- Bump the version on every change. The store ships updates by comparing
manifest.jsonversiontoplugins.jsonlatest_version. Forget it and users never get your change — and CI fails the PR. See topic 6. - Fetch in
update(), draw indisplay(). Never hit the network fromdisplay(). See topic 1. - Cache anything you fetch through
self.cache_manager, namespaced by plugin id. See topic 2. - Import optional core features defensively. Newer capabilities
(
VegasDisplayMode,src.adaptive_layout,src.element_style) don't exist on older cores — guard every import withtry/except ImportErrorand fall back. See topics 3 and 5. - Give deferred/subpackage modules plugin-unique names. Two plugins sharing
a bare module name (
data_model.py) can bind each other's module and fail to load. See topic 7. - Render correctly at every matrix size (64×32, 128×32, 128×64, 256×32). The safety harness enforces it. See topic 5 and topic 7.
- This repo (
ledmatrix-plugins) — plugin source, manifests, config schemas, the registry, and the collision/registry tooling inscripts/. - The core repo (
ChuckBuilds/LEDMatrix) —BasePlugin, the display/cache/font managers, the optional subsystems (src.adaptive_layout,src.element_style), the manifest JSON Schema, and the safety harness (scripts/check_plugin.py). You import from it but you don't edit it here.
Every code reference in this guide points at a real plugin in this repo so you can see the pattern in context. When in doubt, grep the sports scoreboards — they exercise almost every feature.