Plugin development
Oct 15, 2026
Everything a third party might supply is a plugin in plugins/{slug}/.
The manifest
plugin.json:
{
"api": 1,
"slug": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"author": "You",
"description": "What it does.",
"namespace": "Vendor\\MyPlugin",
"requires": { "whbmp": "2.0.0", "php": "8.2" },
"provides": { "payment_gateway": "Vendor\\MyPlugin\\MyGatewayModule" }
}
Use your own vendor namespace. WhbmpPlugins\ is reserved for WHBMP's own plugins.
Loading
The plugin manager reads every manifest, autoloads the namespace from the plugin folder (no Composer step), registers the plugin's service provider and picks up resources/views (as {slug}::), lang and the route files:
| File | Routes |
|---|---|
routes/web.php |
Public |
routes/admin.php |
Admin prefix, admin. names, staff sign-in |
routes/client.php |
/client, client. names, client sign-in |
routes/api.php |
/api |
A plugin's database/migrations run with php artisan migrate, and for addon plugins when the addon is installed.
Types
addon, migration, payment_gateway, domain_registrar, server, compute, ai_provider, fraud_check, captcha. Each type implements a contract from app/Plugins/Contracts. provides may list several types and several classes per type.
servermodules create, suspend and terminate accounts on a shared panel host.computemodules provision, reboot, reinstall and terminate a whole instance on a VPS platform.
Dependencies
"depends": ["licensing"] lists addons that must be active. Activation is refused until they are.
Extension points
Register from the plugin's service provider. Each is tied to an addon so it only applies while the addon is active.
| Method | Adds |
|---|---|
adminMenu() |
Sidebar items |
slot() |
Views rendered where a core page has @pluginSlot('name') |
productType() |
A product type with its own service module |
serviceObserver() |
A hook that follows hosting accounts |
productSettings() |
Extra product-form fields |
productTab() |
A tab on the product form |
adminClientTab() |
A tab on the admin client page |
messageChannel() |
An SMS or WhatsApp provider |
settingsTile() |
A tile on the Settings page |
dashboardTile() |
A card on the dashboard's top row |
knowledgebase() |
A source of help articles for ticket replies and AI drafts |
loginChallenge() |
A second sign-in step |
legacyPasswordVerifier() |
Checks imported password hashes at client sign-in |
Staff alerts come from the core event App\Events\StaffAlertRaised. Alert plugins listen to it.
Safety
A bad manifest, an unknown type, a class outside the plugin's namespace, a reserved namespace, a duplicate type slug or a too-new requires makes WHBMP skip that plugin and report it on the Plugins page. The rest keeps running.
Packaging
A plugin package is a zip with one top folder named after the slug. Installed plugins carry .marketplace.json, which the core updater never overwrites.
Related
- Developer guide
- Building a plugin (start with one command)
- Building a payment gateway plugin
- Testing and releasing a plugin