Found 5 more bare /api/plugins/* paths in PLUGIN_CONFIGURATION_TABS.md
that I missed in the round 2 sweep — they're inside data flow diagrams
and prose ("loaded via /api/plugins/installed", etc.) so the earlier
grep over Markdown code blocks didn't catch them. Fixed all 5 to use
/api/v3/plugins/* (the api_v3 blueprint mount path verified at
web_interface/app.py:144).
Also added a status banner noting that the "Implementation Details"
section references the pre-v3 file layout (web_interface_v2.py,
templates/index_v2.html) which no longer exists. The current
implementation is in web_interface/app.py, blueprints/api_v3.py, and
templates/v3/. Same kind of historical drift I flagged in
PLUGIN_ARCHITECTURE_SPEC.md and the PLUGIN_CUSTOM_ICONS_FEATURE doc.
The user-facing parts of the doc (Overview, Features, Form Generation
Process) are still accurate.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9.5 KiB
Plugin Configuration Tabs
Status note: this doc was written during the rollout of the per-plugin configuration tab feature. The feature itself is shipped and working in the current v3 web interface, but a few file paths in the "Implementation Details" section below still reference the pre-v3 file layout (
web_interface_v2.py,templates/index_v2.html). The current implementation lives inweb_interface/app.py,web_interface/blueprints/api_v3.py, andweb_interface/templates/v3/. The user-facing description (Overview, Features, Form Generation Process) is still accurate.
Overview
Each installed plugin now gets its own dedicated configuration tab in the web interface. This provides a clean, organized way to configure plugins without cluttering the main Plugins management tab.
Features
- Automatic Tab Generation: When a plugin is installed, a new tab is automatically created in the web UI
- JSON Schema-Based Forms: Configuration forms are automatically generated based on each plugin's
config_schema.json - Type-Safe Inputs: Form inputs are created based on the JSON Schema type (boolean, number, string, array, enum)
- Default Values: All fields show current values or fallback to schema defaults
- Reset Functionality: Users can reset all settings to defaults with one click
- Real-Time Validation: Input constraints from JSON Schema are enforced (min, max, maxLength, etc.)
User Experience
Accessing Plugin Configuration
- Navigate to the Plugins tab to see all installed plugins
- Click the Configure button on any plugin card
- You'll be automatically taken to that plugin's configuration tab
- Alternatively, click directly on the plugin's tab button (marked with a puzzle piece icon)
Configuring a Plugin
- Open the plugin's configuration tab
- Modify settings using the generated form
- Click Save Configuration
- Restart the display service to apply changes
Plugin Manager vs Per-Plugin Configuration
- Plugin Manager tab (second nav row): used for browsing the Plugin Store, installing plugins, toggling installed plugins on/off, and updating/uninstalling them
- Per-plugin tabs (one per installed plugin, also in the second
nav row): used for configuring that specific plugin's behavior and
settings via a form auto-generated from its
config_schema.json
For Plugin Developers
Requirements
To enable automatic configuration tab generation, your plugin must:
- Include a
config_schema.jsonfile - Reference it in your
manifest.json:
{
"id": "your-plugin",
"name": "Your Plugin",
"icon": "fas fa-star", // Optional: Custom tab icon
...
"config_schema": "config_schema.json"
}
Note: You can optionally specify a custom icon for your plugin tab. See Plugin Custom Icons Guide for details.
Supported JSON Schema Types
The form generator supports the following JSON Schema types:
Boolean
{
"type": "boolean",
"default": true,
"description": "Enable or disable this feature"
}
Renders as: Toggle switch
Number / Integer
{
"type": "integer",
"default": 60,
"minimum": 1,
"maximum": 300,
"description": "Update interval in seconds"
}
Renders as: Number input with min/max constraints
String
{
"type": "string",
"default": "Hello, World!",
"minLength": 1,
"maxLength": 50,
"description": "The message to display"
}
Renders as: Text input with length constraints
Array
{
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"minItems": 3,
"maxItems": 3,
"default": [255, 255, 255],
"description": "RGB color [R, G, B]"
}
Renders as: Text input (comma-separated values)
Example input: 255, 128, 0
Enum (Select)
{
"type": "string",
"enum": ["small", "medium", "large"],
"default": "medium",
"description": "Display size"
}
Renders as: Dropdown select
Example config_schema.json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "My Plugin Configuration",
"description": "Configure my awesome plugin",
"properties": {
"enabled": {
"type": "boolean",
"default": true,
"description": "Enable or disable this plugin"
},
"message": {
"type": "string",
"default": "Hello!",
"minLength": 1,
"maxLength": 50,
"description": "The message to display"
},
"update_interval": {
"type": "integer",
"default": 60,
"minimum": 1,
"maximum": 3600,
"description": "Update interval in seconds"
},
"color": {
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"minItems": 3,
"maxItems": 3,
"default": [255, 255, 255],
"description": "RGB color [R, G, B]"
},
"mode": {
"type": "string",
"enum": ["scroll", "static", "fade"],
"default": "scroll",
"description": "Display mode"
}
},
"required": ["enabled"],
"additionalProperties": false
}
Best Practices
- Use Descriptive Labels: The
descriptionfield is shown as help text under each input - Set Sensible Defaults: Always provide default values that work out of the box
- Use Constraints: Leverage min/max, minLength/maxLength to guide users
- Mark Required Fields: Use the
requiredarray in your schema - Organize Properties: List properties in order of importance
Form Generation Process
- Web UI loads installed plugins via
/api/v3/plugins/installed - For each plugin, the backend loads its
config_schema.json - Frontend generates a tab button with plugin name
- Frontend generates a form based on the JSON Schema
- Current config values from
config.jsonare populated - When saved, each field is sent to
/api/v3/plugins/configendpoint
Implementation Details
Backend Changes
File: web_interface_v2.py
- Modified
/api/v3/plugins/installedendpoint to includeconfig_schema_data - Loads each plugin's
config_schema.jsonif it exists - Returns schema data along with plugin info
Frontend Changes
File: templates/index_v2.html
New Functions:
generatePluginTabs(plugins)- Creates tab buttons and content for each plugingeneratePluginConfigForm(plugin)- Generates HTML form from JSON SchemasavePluginConfiguration(pluginId)- Saves form data to backendresetPluginConfig(pluginId)- Resets all settings to defaultsconfigurePlugin(pluginId)- Navigates to plugin's tab
Data Flow
Page Load
→ refreshPlugins()
→ /api/v3/plugins/installed
→ Returns plugins with config_schema_data
→ generatePluginTabs()
→ Creates tab buttons
→ Creates tab content
→ generatePluginConfigForm()
→ Reads JSON Schema
→ Creates form inputs
→ Populates current values
User Saves
→ savePluginConfiguration()
→ Reads form data
→ Converts types per schema
→ Sends to /api/v3/plugins/config
→ Updates config.json
→ Shows success notification
Troubleshooting
Plugin Tab Not Appearing
- Ensure
config_schema.jsonexists in plugin directory - Verify
config_schemafield inmanifest.json - Check browser console for errors
- Try refreshing plugins (Plugins tab → Refresh button)
Form Not Generating Correctly
- Validate your
config_schema.jsonagainst JSON Schema Draft 07 - Check that all properties have a
typefield - Ensure
defaultvalues match the specified type - Look for JavaScript errors in browser console
Configuration Not Saving
- Ensure the plugin is properly installed
- Check that config keys match schema properties
- Verify backend API is accessible
- Check browser network tab for API errors
- Ensure display service is restarted after config changes
Migration Guide
For Existing Plugins
If your plugin already has a config_schema.json:
- No changes needed! The tab will be automatically generated.
- Test the generated form to ensure all fields render correctly.
- Consider adding more descriptive
descriptionfields.
If your plugin doesn't have a config schema:
- Create
config_schema.jsonbased on your current config structure - Add descriptions for each property
- Set appropriate defaults
- Add validation constraints (min, max, etc.)
- Reference the schema in your
manifest.json
Backward Compatibility
- Plugins without
config_schema.jsonstill work normally - They simply won't have a configuration tab
- Users can still edit config via the Raw JSON editor
- The Configure button will navigate to a tab with a friendly message
Future Enhancements
Potential improvements for future versions:
- Advanced Schema Features: Support for nested objects, conditional fields
- Visual Validation: Real-time validation feedback as user types
- Color Pickers: Special input for RGB/color array types
- File Uploads: Support for image/asset uploads
- Import/Export: Save and share plugin configurations
- Presets: Quick-switch between saved configurations
- Documentation Links: Link schema fields to plugin documentation
Example Plugins
See these plugins for examples of config schemas:
hello-world: Simple plugin with basic typesclock-simple: Plugin with enum and number types
Support
For questions or issues:
- Check the main LEDMatrix wiki
- Review plugin documentation
- Open an issue on GitHub
- Join the community Discord