Creating a Plugin
Step 1: Directory Structure
plugins/my-plugin/
├── plugin.json # Required: manifest
├── src/
│ └── MyPlugin.php # Required: entry class
├── routes/
│ ├── web.php # Optional: web routes
│ └── api.php # Optional: API routes (public, no CSRF)
├── views/ # Optional: Blade templates
├── database/
│ └── migrations/ # Optional: Laravel migrations
├── config/
│ └── my-plugin.php # Optional: merged as plugins.my-plugin
├── lang/ # Optional: translations
├── storage/ # Optional: file-based stores
└── README.md # Optional: documentation
Step 2: Plugin Manifest (plugin.json)
{
"name": "My Plugin",
"slug": "my-plugin",
"version": "1.0.0",
"entry": {
"file": "src/MyPlugin.php",
"class": "MyPlugin\\MyPlugin"
},
"autoload": {
"psr-4": {
"MyPlugin\\": "src/"
}
},
"requires": {
"framework": ">=1.0",
"php": ">=8.3",
"plugins": {}
},
"provides": ["checkout.price.calculate", "page.banner"],
"capabilities": [],
"xilancerMetaData": {
"plugin_type": "external"
}
}
Manifest Fields
| Field | Required | Description |
|---|---|---|
name | Yes | Human-readable plugin name |
slug | Yes | Lowercase alphanumeric + dashes |
version | Yes | Semver format |
entry.file | Yes | Relative path to entry PHP file |
entry.class | Yes | Fully-qualified entry class name |
autoload.psr-4 | No | PSR-4 namespace map |
requires.framework | No | Framework version constraint |
requires.php | No | PHP version constraint |
requires.plugins | No | Plugin dependencies |
provides | No | Hook/slot names this plugin provides |
xilancerMetaData | No | Legacy metadata (admin menus, blade hooks) |
Step 3: Entry Class
<?php
declare(strict_types=1);
namespace MyPlugin;
use PluginsFramework\Plugins\PluginContext;
use PluginsFramework\Plugins\PluginInterface;
final class MyPlugin implements PluginInterface
{
public function __construct(private PluginContext $ctx) {}
public function boot(): void
{
// Register hooks, slots, registry entries
}
}
The entry class receives a PluginContext with three services:
$this->ctx->hooks // HookManager — actions and filters
$this->ctx->slots // SlotRenderer — HTML injection points
$this->ctx->registry // Registry — structured contributions (gateways, menus, etc.)
Step 4: Activate
php core/artisan plugins list # Verify discovery
php core/artisan plugins activate my-plugin
Or via Admin > Plugin Manage > Upload Plugin (zip with plugin.json at root).
Last updated: September 2026
Still stuck?
Our support team is ready to help you get set up.

