Plugin System Overview
Extend WebVB Studio with custom controls and functions. Plugins are self-contained JSON packages
that can be installed, shared, and distributed as .vbplugin files.
What Plugins Can Provide
Custom Controls
New visual controls that appear in the Toolbox, render in the Designer with live preview, and fully function at runtime. Star ratings, color pickers, progress bars—anything you can imagine.
Custom Functions
New functions available globally in VB and Python code. Add utility helpers, validators, formatters, or domain-specific operations your projects need.
Custom CSS Styles
Inject global CSS styles that your controls or the entire application can use. Define animations, keyframes, and styling that persists while the plugin is active.
Help Documentation
Include rich HTML help content that describes your controls and functions. Users can view this documentation from the Plugin Manager.
Architecture Overview
The plugin system is built around a central PluginManager singleton that handles the entire lifecycle. Plugins are stored in localStorage and loaded on app startup.
Plugin Lifecycle
active.
Plugin File Format (.vbplugin)
A .vbplugin file is simply a JSON file
containing a PluginDefinition object.
Everything the plugin needs—code, metadata, styles, and documentation—is bundled into this single file.
{
"pluginApiVersion": "1.0",
"metadata": { ... },
"controls": [ ... ],
"functions": [ ... ],
"styles": "CSS string",
"helpContent": "HTML string"
} Key Design Decisions
- ● Self-contained: No external dependencies or file references. Everything is inlined.
- ● Code as strings: Renderer code and function implementations are JavaScript strings executed via
new Function(). - ● Human-readable: The JSON format is easy to edit by hand or generate programmatically.
- ● Portable: Share plugins by sending a single file, pasting JSON, or hosting on any server.
Complete Type Reference
Below is the full TypeScript interface reference for every object in the plugin system. These types define the contract between your plugin and WebVB Studio.
interface PluginDefinition
The root object of every plugin. This is what gets serialized into the .vbplugin file.
interface PluginDefinition {
pluginApiVersion: '1.0'; // Must be "1.0"
metadata: PluginMetadata; // Required: name, id, version, author
controls?: PluginControlDef[]; // Optional: custom controls
functions?: PluginFunctionDef[];// Optional: custom functions
styles?: string; // Optional: CSS to inject
helpContent?: string; // Optional: HTML documentation
} interface PluginMetadata
Identifies and describes your plugin. The id, name, and version fields are required.
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Unique identifier, e.g. "com.example.colorpicker" |
| name | string | Yes | Human-readable display name |
| version | string | Yes | Semantic version, e.g. "1.0.0" |
| description | string | Yes | Short description shown in Plugin Manager |
| author | PluginAuthor | Yes | Object with name, optional email and url |
| icon | string | No | Emoji or data:image URI for the plugin icon |
| category | string | No | Category for organizing, e.g. "Input", "Display", "Functions" |
| tags | string[] | No | Searchable tags like ["rating", "input"] |
| license | string | No | License identifier, e.g. "MIT", "Apache-2.0" |
| homepage | string | No | Project URL or documentation link |
| minAppVersion | string | No | Minimum WebVB Studio version required |
interface PluginControlDef
Defines a custom visual control. Each control provides renderers for both designer preview and runtime execution.
| Property | Type | Description |
|---|---|---|
| typeName | string | Unique name, e.g. "StarRating". Registered as "plugin:com.example/StarRating" |
| displayName | string | Label shown in the Toolbox panel |
| icon | string | Emoji or data URI for the Toolbox icon |
| description | string | Tooltip shown when hovering in the Toolbox |
| toolboxCategory | string? | Toolbox section (defaults to "Plugins") |
| defaultWidth | number | Width in pixels when first placed on a form |
| defaultHeight | number | Height in pixels when first placed on a form |
| properties | PluginPropertyDef[] | Property schema for the Properties panel |
| events | PluginEventDef[] | Events the control can fire |
| designerRenderHtml | string | Required. JS function body receiving (props), must return HTML string |
| runtimeRenderHtml | string | Required. JS function body receiving (props, controlId), returns HTML |
| runtimeInitCode | string? | Runs after mount. Receives (element, props, controlId, fireEvent) |
| runtimeCleanupCode | string? | Runs on unmount. Clean up intervals, listeners, etc. |
| runtimePropertyChangeCode | string? | Called when property changes. Receives (element, propName, newValue, oldValue, props) |
interface PluginPropertyDef
Defines a property that appears in the Properties panel when the control is selected in the designer.
interface PluginPropertyDef {
id: string; // Property key, e.g. "Value", "MaxStars"
label: string; // Display label in Properties panel
type: 'text' | 'number' | 'boolean' | 'color' | 'select' | 'textarea';
defaultValue?: any; // Default when control is first created
options?: string[]; // Choices for 'select' type
description?: string; // Tooltip text
category?: string; // Group heading, e.g. "Appearance", "Behavior"
} Supported Property Types
text number boolean color select options[]textarea interface PluginEventDef
Declares an event that the control can fire. Users write event handlers for these in VB/Python code.
interface PluginEventDef {
name: string; // Event name, e.g. "Change", "Click", "ColorSelected"
description?: string; // Explains when this event fires
params?: string[]; // Parameters passed to the handler, e.g. ["NewValue"]
} Example: If your control defines an event
Change with params
["NewValue"], users write:
Sub StarRating1_Change(NewValue)
MsgBox "Rating: " & NewValue
End Sub def StarRating1_Change(NewValue):
MsgBox(f"Rating: {'{'}NewValue{'}'}") interface PluginFunctionDef
Defines a custom function available in VB and/or Python code. Functions are registered globally when the plugin is active.
| Property | Type | Description |
|---|---|---|
| name | string | Function name, callable in VB/Python code |
| description | string | Description for help and IntelliSense autocomplete |
| params | PluginFunctionParam[] | Parameter definitions (name, type, description, optional, defaultValue) |
| returnType | string? | Return type description for documentation |
| jsCode | string | Required. JavaScript function body. Parameters are available as named variables. |
| isAsync | boolean? | Whether the function returns a Promise |
| category | string? | Category for help grouping, e.g. "String", "Math" |
interface InstalledPlugin
Wraps a PluginDefinition with runtime state. This is what the PluginManager stores and tracks.
interface InstalledPlugin {
definition: PluginDefinition;
status: 'active' | 'disabled' | 'error';
installedAt: string; // ISO 8601 date string
error?: string; // Error message if status is 'error'
} Control Type Namespacing
To avoid collisions between plugins, all plugin control types are automatically namespaced.
When you define a control with typeName: "StarRating"
in a plugin with id: "com.webvb.starrating", the control
is registered internally as:
plugin:com.webvb.starrating/StarRating
The format is plugin:{pluginId}/{typeName}.
This ensures two plugins can both define a "ColorPicker" control without conflict.
Helper functions are provided:
// Build a namespaced type string
getPluginControlType("com.webvb.starrating", "StarRating")
// → "plugin:com.webvb.starrating/StarRating"
// Check if a type is from a plugin
isPluginControlType("plugin:com.webvb.starrating/StarRating")
// → true
// Parse back to components
parsePluginControlType("plugin:com.webvb.starrating/StarRating")
// → { pluginId: "com.webvb.starrating", typeName: "StarRating" } PluginManager API
The pluginManager singleton
provides the full API for managing plugins. Import it from services/PluginManager.
Installation
install(definition: PluginDefinition): { success: boolean; error?: string } uninstall(pluginId: string): boolean Enable / Disable
setEnabled(pluginId: string, enabled: boolean): boolean active
and disabled states.
Enabling re-injects CSS styles; disabling removes them.
Query APIs
getPlugin(pluginId): InstalledPlugin | undefined Get a specific plugin by ID.
getAllPlugins(): InstalledPlugin[] Get all installed plugins (active, disabled, and error).
getActivePlugins(): InstalledPlugin[] Get only plugins with 'active' status.
getPluginControls(): Array<{ controlType, control, pluginId, pluginName }> Get all controls from active plugins, with their namespaced types.
getPluginFunctions(): Array<{ fn, pluginId, pluginName }> Get all functions from active plugins.
getDefaultProperties(controlType): Record<string, any> Get default property values for a plugin control type.
getPropertySchema(controlType): PluginPropertyDef[] Get the property schema for the Properties panel.
Import / Export
exportPlugin(pluginId: string): string | null .vbplugin files for distribution.
importPlugin(jsonString: string): { success: boolean; error?: string; pluginId?: string } React Subscriptions
subscribe(listener: () => void): () => void function usePlugins() {
const [plugins, setPlugins] = useState(
pluginManager.getAllPlugins()
);
useEffect(() => {
return pluginManager.subscribe(() => {
setPlugins(pluginManager.getAllPlugins());
});
}, []);
return plugins;
} Runtime Helpers
createRendererFunction(codeString): (props, controlId?) => string new Function().
Returns a fallback error renderer if compilation fails. Used internally for
designerRenderHtml and runtimeRenderHtml.
createPluginFunction(fn: PluginFunctionDef): (...args) => any new Function() arguments.
Supports async functions when isAsync: true.
getStdLibFunctions(): Record<string, Function> Code Execution Model
Plugin code runs in a semi-sandboxed environment. Both renderer functions and custom functions are compiled
using new Function(), which provides
separation from the main application scope.
Designer Renderer
The designerRenderHtml code string becomes:
new Function('props', 'controlId', yourCodeString); Receives the current property values. Must return an HTML string for the designer preview.
Runtime Renderer
The runtimeRenderHtml code works identically but typically includes
interactive elements (event handlers, hover effects, etc.).
Runtime Init Code
The runtimeInitCode runs once after the control is mounted to the DOM.
It has access to these variables:
element props controlId fireEvent(name, data) setProperty(name, value) Custom Functions
Function code becomes:
new Function('param1', 'param2', ..., yourJsCode); Parameters are injected as named arguments. The code should use return to produce a value.
Built-in Example Plugins
WebVB Studio includes four example plugins in the Gallery tab of the Plugin Manager. These demonstrate different plugin capabilities and serve as templates for your own plugins.
Star Rating
com.webvb.starratingInteractive star rating with configurable max stars, colors, and sizes. Click to set value.
Progress Bar
com.webvb.progressbarAnimated progress bar with stripes, labels, and multiple visual styles (flat, rounded, pill).
Color Picker
com.webvb.colorpickerVisual color palette with preset swatches, native picker integration, and editable hex input.
Utility Functions
com.webvb.utilities7 helper functions: Slugify, Truncate, Capitalize, RandomRange, Clamp, IsEmail, IsURL.
Managing Plugins (UI)
The Plugin Manager dialog (accessible from the toolbar) provides a full UI for managing plugins with four tabs:
Installed
View all installed plugins with their status. Enable/disable plugins with a toggle, export them
as .vbplugin files, or uninstall them completely.
Gallery
Browse and install built-in example plugins with one click. See descriptions, categories, and tags before installing. Already installed plugins show their current status.
Import
Load plugins from external .vbplugin files using
a file picker, or paste raw JSON directly into the text area and click Install.
Create
A built-in JSON editor with a starter template. Write your plugin definition directly in the browser, validate it, and install immediately. Great for prototyping new plugins.