Plugin Development Guide
Learn how to create custom plugins to extend VERA's functionality with your own specialized nodes, tools, and integrations.
Plugin Architecture
Understanding how plugins integrate with VERA's core systems.
Plugin System Overview
Understanding how plugins integrate with VERA
- Plugin discovery and loading mechanism
- Node factory registration system
- Plugin isolation and sandboxing
- Version compatibility checking
- Plugin dependency management
Plugin Structure
Required files and directory structure
- plugin.json manifest file
- Python package structure
- Node implementation files
- Resource and asset organization
- Plugin metadata requirements
Plugin Lifecycle
How plugins are loaded and managed
- Plugin discovery on startup
- Node registration process
- Plugin enable/disable functionality
- Update and compatibility checks
- Plugin cleanup on shutdown
Step-by-Step Development Guide
Follow these steps to create your first VERA plugin.
Step 1: Setup Development Environment
Prepare your development workspace
What you'll do:
- Install Python 3.8+ with pip
- Set up virtual environment
- Install VERA development version
- Install plugin development dependencies
- Set up code editor with Python support
Example Code:
# Create plugin directory
mkdir my_custom_plugin
cd my_custom_plugin
# Create manifest.json
cat > manifest.json << 'EOF'
{
"id": "my_custom_plugin",
"name": "My Custom Plugin",
"version": "1.0.0",
"author": "Your Name",
"description": "A custom plugin for VERA",
"entry_module": "my_plugin.py"
}
EOFStep 2: Create Plugin Project Structure
Set up the basic plugin skeleton
What you'll do:
- Create plugin directory structure
- Write plugin.json manifest file
- Create __init__.py files
- Set up Python package configuration
- Initialize version control
Example Code:
# Plugin directory structure
my_custom_plugin/
├── manifest.json # Plugin manifest (REQUIRED)
├── my_plugin.py # Entry module (REQUIRED)
├── icons/ # Optional custom icons
│ └── my_icon.png
└── README.md # Optional documentationStep 3: Write Plugin Manifest
Create the plugin.json configuration file
What you'll do:
- Define plugin metadata
- Specify plugin dependencies
- List custom node types
- Configure plugin settings
- Set compatibility requirements
Example Code:
{
"id": "my_custom_plugin",
"name": "My Custom Plugin",
"version": "1.0.0",
"author": "Your Name",
"description": "A custom plugin for VERA",
"entry_module": "my_plugin.py"
}Step 4: Implement Custom Nodes
Create your custom node classes
What you'll do:
- Inherit from BaseNode class
- Implement required methods
- Define input/output ports
- Add node properties and UI
- Handle node execution logic
Example Code:
from core.nodes import BaseNode
class MyCustomNode(BaseNode):
"""Custom node for special data processing."""
def __init__(self):
super().__init__(node_type="my_custom_node", title="My Custom Node")
# Add input ports
self.add_input_port("input_data", data_type="string")
self.add_input_port("parameters", data_type="string")
# Add output ports
self.add_output_port("processed_data", data_type="string")
self.add_output_port("statistics", data_type="string")
# Set default properties
self.set_property("processing_mode", "standard")
self.set_property("enable_logging", True)
def execute(self, inputs: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""Execute the node's processing logic."""
try:
# Get input data
input_data = inputs.get("input_data") if inputs else None
parameters = inputs.get("parameters", {}) if inputs else {}
if input_data is None:
raise ValueError("Input data is required")
# Process the data
processed_data, statistics = self._process_data(input_data, parameters)
# Return results
return {
"processed_data": processed_data,
"statistics": statistics
}
except Exception as e:
self.logger.error(f"Node execution failed: {str(e)}")
raise
def _process_data(self, data, parameters):
"""Implement your custom processing logic here."""
# Example processing - replace with your logic
import pandas as pd
if isinstance(data, list) and len(data) > 0:
df = pd.DataFrame(data)
elif hasattr(data, '__iter__'):
df = pd.DataFrame(list(data))
else:
raise ValueError("Invalid input data format")
# Apply your processing
processed_df = self._apply_custom_processing(df, parameters)
# Calculate statistics
stats = {
'rows_processed': len(processed_df),
'columns': list(processed_df.columns),
'processing_mode': self.get_property("processing_mode")
}
return processed_df, stats
def _apply_custom_processing(self, df, parameters):
"""Implement your specific data processing logic."""
# This is where your custom logic goes
# Example: add a new calculated column
df['custom_score'] = df.mean(axis=1)
return df
def _inline_summary(self) -> list[str]:
"""Display node status in the canvas."""
mode = self.get_property("processing_mode")
return [
f"Mode: {mode}",
f"Logging: {'Enabled' if self.get_property('enable_logging') else 'Disabled'}"
]Step 5: Register Plugin with VERA
Make your plugin discoverable by VERA
What you'll do:
- Implement plugin registration function
- Handle node factory integration
- Set up plugin discovery
- Configure plugin loading
- Test plugin registration
Example Code:
def register(api):
"""Register plugin nodes with VERA."""
api.register_node(
node_type="my_custom_node",
node_class=MyCustomNode,
display_name="My Custom Node",
description="A custom node for data processing",
category="Examples",
icon_relpath="icons/my_icon.png"
)Step 6: Test and Debug Plugin
Ensure your plugin works correctly
What you'll do:
- Create test workflows
- Test node functionality
- Debug execution errors
- Validate input/output handling
- Test edge cases and error conditions
Example Code:
# Testing your plugin:
1. In VERA, go to Plugins → Add Plugin…
2. Select your plugin folder
3. Choose Plugins → Reload Plugins
4. Look for your node in the toolbox under the specified category
5. Create a workflow and test the node functionality
# If you encounter issues:
- Check the console output for error messages
- Verify manifest.json has correct format
- Ensure entry_module matches your Python file name
- Make sure register(api) function exists and is properly implementedStep 7: Package and Distribute
Prepare your plugin for distribution
What you'll do:
- Create setup.py for pip installation
- Write comprehensive README
- Create example workflows
- Package plugin for distribution
- Publish to plugin registry
Example Code:
# Create ZIP archive for distribution
zip -r my_custom_plugin.zip my_custom_plugin/
# Alternative: Share the folder directly
# Users can install from folder using Plugins → Add Plugin…
# Distribution tips:
- Include a README.md with usage instructions
- Test your plugin on different systems
- Provide example workflows
- Document any dependencies
- Consider creating a GitHub repositoryAdvanced Topics
Take your plugin development to the next level with these advanced techniques.
Node UI Customization
Create custom user interfaces for your nodes
- Custom property dialogs
- Inline node summaries
- Interactive controls
- Progress indicators
- Real-time status updates
Plugin Configuration
Advanced plugin configuration options
- Plugin settings management
- User preferences
- Configuration validation
- Settings persistence
- Plugin-specific options
Error Handling & Logging
Robust error handling and debugging
- Exception handling strategies
- Logging best practices
- Debug mode functionality
- User-friendly error messages
- Plugin crash recovery
Performance Optimization
Optimize plugin performance
- Memory management
- Asynchronous processing
- Caching strategies
- Resource cleanup
- Performance profiling
Plugin Security
Security considerations for plugin development
- Input validation
- Secure file operations
- Network security
- API key management
- Permission handling
Example Plugin Projects
Get inspired by these example plugin projects of varying complexity.