Files
ChuckandClaude Opus 5.5 61e462c635 refactor: remove the skin system and the unused src/base_classes package (#615)
* refactor: remove the skin system

Skins never rendered with the current scoreboard plugins: the only hook was
SportsCore._render_game in src/base_classes, which no plugin builds on, so
the UI and store already treated them as unsupported. The owner decided on
2026-09-23 to remove them outright.

Removed src/skin_system/ (runtime, base class, fixtures), skins/,
scripts/validate_skin.py and their tests; the store's "type": "skin"
installer, uninstaller and hide/refuse filters (the official registry lists
no skins); SchemaManager.inject_skin_selector; and GET /api/v3/skins.

Stored skin/skin_options config values are handled in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(config): drop retired skin/skin_options keys instead of validating them

A config.json written while the skin system existed can carry skin and
skin_options in any plugin section, and most plugin schemas set
additionalProperties: false. They are no longer core plugin properties;
RETIRED_PLUGIN_KEYS in schema_manager lists them and
drop_retired_plugin_keys removes them (unless the plugin's own schema
declares the name) in prepare_plugin_config, which loading, hot reload,
GET /plugins/config and both web saves already share, and in
validate_config_against_schema for callers that validate a raw section.
POST /plugins/config and /config/main also drop them from the stored
section they merge into, so they leave config.json on the next save.

Tests cover the load path (real PluginManager.load_plugin: no schema
warning, not degraded), raw and prepared validation,
validate_all_plugin_configs, and the JSON, form and /config/main saves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: remove the unused src/base_classes package

No scoreboard plugin builds on src.base_classes: the nine monorepo
scoreboards ship their own sports.py and share code through src/common
(docs/SPORTS_UNIFICATION.md), and none of the third-party registry plugins
imports it. The one import anywhere, baseball-scoreboard's
rankings_manager.py, is a lazy import of ESPNDataSource in a class nothing
instantiates.

Removed the package and the eight test files that only tested it
(test_api_extractors, test_data_sources, test_sports_base_characterization,
test_sports_capabilities, test_sports_core_promotions,
test_sports_logo_cache_bounded, test_sports_modes_promotions,
test_sports_odds_fanout). test_common_is_hardware_free no longer lists
src.base_classes as a forbidden import, and comments in sports_helpers.py
and base_odds_manager.py stop pointing at it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: drop the skin system and src/base_classes from the docs

Deletes docs/SKIN_SYSTEM.md and docs/CREATING_SKINS.md and every link to
them (docs/README.md, README.md, PLUGIN_DEVELOPMENT_GUIDE.md, the /skins
section of REST_API_REFERENCE.md), the skin section of CLAUDE.md and the
term in PRODUCT.md. SPORTS_UNIFICATION.md now says src/base_classes was
removed and shared code lives in src/common, in the Layering section and
the view-model-contract rule. Other docs stop pointing at the removed
package. CHANGELOG records both removals under Unreleased.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(store): hide and refuse registry entries that aren't plugins

The skin filters went with the skin system, but a custom registry can still
list "type": "skin" entries, and installing one as a plugin would unpack it
into the plugins directory. PluginStoreManager.is_plugin_entry() (a missing
type means plugin) now hides non-plugin entries from the store and
custom-registry listings, and install refuses them, in the route with a
clear 400 and in _install_plugin_impl for any other caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 16:33:24 -04:00

6.0 KiB

Product

Platform

web

Users

Designed novice-first, with power tools kept within reach.

  • Primary: hobbyist builders. People who assembled an LED matrix panel on a Raspberry Pi, often by following the install video, and are frequently new to Linux and the Pi. They set the display up once (panel size, timezone, WiFi), install and enable a few plugins, then come back occasionally to tweak what the panel shows. They usually reach the control panel from a phone or laptop on their home network, sometimes as an installed home-screen app.
  • Secondary: tinkerers and plugin developers. Comfortable with SSH, config.json, and GitHub. They lean on the Config Editor, Logs, Cache, Operation History, Tools, GitHub-repo installs, and per-plugin config while building or debugging. Their tools must stay reachable without sitting in the novice's path.

Product Purpose

LEDMatrix turns a Raspberry Pi and an RGB LED matrix panel into an information-rich display (clock, weather, calendar, sports scores, stocks, music, and more) through a plugin platform. The web control panel ("LED Matrix Control") is where the display gets configured, extended, and kept healthy.

Success means a builder gets from a freshly flashed Pi to a working, personalized display without needing a terminal, and can keep it running (updates, recovery, troubleshooting) the same way.

Positioning

Four strengths define LEDMatrix, and future work must protect all of them:

  1. Plugin ecosystem. The core ships only starlark-apps and web-ui-info; everything else comes from the built-in Plugin Store (the official ledmatrix-plugins monorepo), third-party GitHub repos, or Starlark (Tidbyt-style) apps. Each installed plugin gets its own configuration tab, generated from its schema.
  2. Runs on tiny Pis. The UI is served by the same device that drives the matrix, on boards as small as the Pi Zero 2 W (512 MB), Pi 3/3B+, and the 1 GB Pi 4.
  3. Recovers without SSH. WiFi access-point fallback with a captive setup page, backup & restore, in-UI updates, live logs, diagnostics, service control, and plugin health let users fix problems from the browser.
  4. Open and community-led. GPL-3.0, a Discord community, and contributions welcome. The maintainer (ChuckBuilds) builds in public and openly relies on AI development tools.

Operating Context

  • Access. Served on the local network at http://<pi-ip>:5000 by the ledmatrix-web service. It is installable as a PWA (web_interface/static/v3/manifest.json, short name "LEDMatrix").
  • First run. When the Pi has no network it creates its own WiFi access point, so the captive setup page (templates/v3/captive_setup.html) may be the very first screen a user sees, on a phone, with no internet connection.
  • Navigation.
    • System tabs: Overview, General, WiFi, Schedule, Display, Rotation, Config Editor, Backup & Restore, Fonts, Logs, Cache, Operation History, Tools.
    • A second row holds Plugin Manager (with the Plugin Store), Starlark Apps, and one tab per installed plugin.
  • Live data. The Overview shows system stats (CPU, memory, temperature, power/throttling) and a live display preview, streamed over SSE.
  • Getting Started checklist. The Overview's first-run checklist runs: set panel size → set timezone → install a plugin → enable it → configure it.
  • Development. python3 scripts/dev_server.py gives a browser preview without the display loop; python3 run.py -e runs the full display in emulator mode.

Capabilities and Constraints

  • Hard constraint: plugin UI compatibility. Third-party plugins rely on JSON Schema (Draft-7) generated config forms, the widget registry (static/v3/js/widgets/), x-secret fields, and plugin web-UI actions. UI changes must keep these working.
  • Config storage. Plugin configuration lives in config/config.json and secrets in config/config_secrets.json, never in plugin directories, so configs survive reinstalls.
  • Stack. An existing Flask + HTMX + Alpine.js app with Jinja templates (web_interface/templates/v3/) and static JS/CSS (web_interface/static/v3/), with self-hosted vendor assets.
  • Terminology. Plugin, Plugin Store, Starlark app, rotation, display duration, Vegas Scroll Mode, on-demand, AP mode.
  • Open decisions (offered during init, not adopted as constraints):
    • Whether the UI must work fully offline, with no CDN fallbacks at runtime.
    • Whether a Node/CSS build step is acceptable for contributors.
    • Whether a formal accessibility standard (e.g. WCAG 2.2 AA) is a requirement.

Brand Commitments

  • Names. The product is "LEDMatrix" and the web UI is titled "LED Matrix Control". The maintainer brand is ChuckBuilds.
  • Voice. Friendly, honest, and learning-in-public, as in the README.
  • App icons. They live in web_interface/static/v3/icons/.

No other visual identity has been made binding.

Evidence on Hand

  • Photos. Real photographs of running displays are linked in README.md (clock, weather, calendar, NHL/MLB/NFL/NCAA, stocks, music).
  • Video. YouTube install and walkthrough videos from ChuckBuilds.
  • Docs. Extensive documentation in docs/, e.g. WEB_INTERFACE_GUIDE.md, GETTING_STARTED.md, WIFI_NETWORK_SETUP.md, LOW_MEMORY_BOARDS.md, PLUGIN_STORE_GUIDE.md.
  • Absences. There are no testimonials, user counts, or benchmark figures. Do not fabricate them.

Product Principles

  1. Novice path first, power one click away. Default views serve the first-time builder, while advanced tools stay discoverable for tinkerers.
  2. Never strand the user at a terminal. Every setup, recovery, and troubleshooting task has a browser path, including from the AP-mode captive page.
  3. Respect the Pi. Every feature is paid for in memory and CPU on a Pi Zero 2 W that is also driving the display.
  4. The ecosystem is the product. Plugins, including third-party ones, must feel first-class and keep working across core UI changes.
  5. Honest and welcoming. Plain language, truthful status, and no overstated claims, in keeping with an open, community-built project.