Plugin Development Setup
This guide explains how to develop and test plugins locally without going through a ZIP upload cycle on every change.
How it works
The plugins/ directory at the repository root is mounted into the backend container at /plugins.
When you install a plugin from this directory, the backend creates a symlink from its internal plugin folder to your source directory instead of copying files.
This means:
- Python changes are picked up automatically by
uvicorn --reload(dev mode). - Frontend bundle changes are served immediately from the same symlinked path.
Prerequisites
- Docker and Docker Compose installed.
- Run the development stack:
docker compose -f docker-compose.dev.yml up
The dev compose file mounts both ./backend and ./plugins into the backend container, enabling live reload for all Python code.
Directory structure
Place each plugin in its own subdirectory under plugins/:
plugins/
├── my-plugin/
│ ├── plugin.json # required manifest
│ ├── main.py # FastAPI router (optional)
│ ├── models.py # SQLAlchemy models (optional)
│ └── frontend/
│ └── index.js # compiled frontend bundle (optional)
└── another-plugin/
└── plugin.json
The directory name must match the id field in plugin.json.
Installing a local plugin
- Log in as an admin and go to Admin → Plugins.
- The Local source plugins section lists every plugin found in
plugins/. - Click Install next to the plugin you want to activate.
The backend reads the manifest, loads the Python module, creates any database tables, and mounts the router — all without copying any files.
Making changes
| Change type | What to do |
|---|---|
| Python (backend) | Save the file — uvicorn --reload restarts automatically. |
| Frontend bundle | Rebuild the bundle inside the plugin's frontend/ directory and reload the page. |
plugin.json manifest | Uninstall then reinstall from the admin panel to pick up new metadata. |
Environment variable
The path to the local plugins directory defaults to /plugins (the docker mount point).
To override it, set LOCAL_PLUGINS_DIR in the backend environment:
# docker-compose.dev.yml (already configured)
environment:
- LOCAL_PLUGINS_DIR=/plugins
Uninstalling
Click Uninstall in the admin panel. For locally-installed plugins, only the symlink is removed — your source files in plugins/ are untouched.
Database tables created by the plugin are dropped (same behaviour as ZIP-installed plugins).
Deploying a finished plugin
Once development is complete, package the plugin as a ZIP and install it via the standard Install plugin (.zip) button, or distribute the ZIP to other instances. See Authoring Plugins for the full packaging guide.