Plugin structure
Create a FeatherPanel plugin with the built-in plugin manager, the files and folders a plugin can have, how they are loaded and how to work on one locally.
On this page
A plugin is a folder in backend/storage/addons/ named after its identifier. When the backend boots (once per
worker in the Docker image, once per request in classic mode) it loads each plugin whose conf.yml is valid and whose entry class matches. The
plugin overview covers installing plugins as an admin; this page is for writing one.
Create a plugin from a template
Turn on developer mode in the admin settings, then open Admin > Dev > Plugins and choose Create Plugin. You pick a name, an identifier, authors, flags, dependencies and one of five templates:
| Template | What you get |
|---|---|
| Empty | conf.yml and the basic directories. |
| Fresh | A clean structure with small examples. |
| Starter | Every example file: route, controller, model, migration, cron job, CLI command, event handler, frontend assets. |
| Theme pack | Frontend/theme.json and theme.css, see Themes and UI packs. |
| UI pack | Frontend/ui.json with a slot action, see Themes and UI packs. |
The identifier must be unique and may only contain letters, digits and _. The hasEvents flag is always set, because the panel registers a
plugin’s hooks through it.
Folder layout
storage/addons/myplugin/
├── conf.yml manifest, see the manifest page
├── MyPlugin.php entry class (name = plugin.name)
├── Routes/ PHP route files, loaded automatically
├── Controllers/ your controllers (App\Addons\myplugin\Controllers)
├── Chat/ database models, by convention
├── Events/ your event handler classes
├── Migrations/ .sql files, run on install and by the migrate command
├── Cron/ jobs run by the cron runner
├── Commands/ commands added to the panel CLI
├── Public/ static files, exposed at /addons/myplugin/
└── Frontend/
├── sidebar.json pages in the client, admin, server, VDS and WebSpace sidebars
├── widgets.json widgets on panel pages
├── index.js, index.css loaded on every panel page
└── Components/ HTML for pages and widgets, served at /components/myplugin/
Only conf.yml and the entry class are required. Everything else is picked up when it exists.
How each part is loaded
| Part | Loaded by |
|---|---|
| Entry class | The plugin manager, which calls processEvents() once when the backend boots. See worker mode. |
Routes/*.php | The router, together with the core route files. See Routes and permissions. |
Migrations/*.sql | The installer when the plugin is installed, and php cli migrate. See Migrations and storage. |
Cron/*.php | The cron runner on each run. Each file must hold the class App\Addons\<identifier>\Cron\<FileName> with a run() method. |
Commands/*.php | The panel CLI. Each class implements App\Cli\CommandBuilder. |
Frontend/ | The frontend, through /api/system/plugin-js, /api/system/plugin-css and the sidebar and widget endpoints. See Frontend. |
Public/, Frontend/Components/ | Linked into public/addons/<identifier> and public/components/<identifier> on install. Resync on the plugin page recreates the links. |
Develop locally
- Run the panel from source or with Docker, see Installation.
- Create the plugin from a template, or copy a folder into
backend/storage/addons/. In the Docker setup that path is/var/www/html/storage/addonsinside the backend container. - If you copied files by hand, run
php cli migratefor the migrations, and use Resync on the plugin page soPublic/andFrontend/Components/are linked. - Reload the panel. There is no build step on the panel side. In the Docker image the API runs in worker mode, so use Resync or restart the backend after changing PHP files, see worker mode.
Build your first plugin walks through these steps with a small working plugin.
Next steps
Frequently asked questions
The Plugin Manager under Admin > Dev and plugin export both need developer mode, which you turn on in the admin settings. A plugin you copy into storage/addons by hand loads without it.
App\Addons\<identifier>. Composer maps App\Addons\ to backend/storage/addons/, so App\Addons\myplugin\Controllers\Foo lives in storage/addons/myplugin/Controllers/Foo.php.