Xgenious/ docs

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

FieldRequiredDescription
nameYesHuman-readable plugin name
slugYesLowercase alphanumeric + dashes
versionYesSemver format
entry.fileYesRelative path to entry PHP file
entry.classYesFully-qualified entry class name
autoload.psr-4NoPSR-4 namespace map
requires.frameworkNoFramework version constraint
requires.phpNoPHP version constraint
requires.pluginsNoPlugin dependencies
providesNoHook/slot names this plugin provides
xilancerMetaDataNoLegacy 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.
Get support