Plugin System¶
Niamoto uses plugins for the parts of the pipeline that change from one project to another: loading data, computing grouped outputs, rendering widgets, exporting files, and publishing artifacts.
Plugin families¶
The runtime defines five plugin types in src/niamoto/core/plugins/base.py:
loaders
transformers
widgets
exporters
deployers
Each family has its own abstract base class and its own execution contract.
Registration¶
Built-in and custom plugins register through PluginRegistry in
src/niamoto/core/plugins/registry.py.
The registry stores plugins by type and name. Services resolve the plugin they need from that registry instead of importing implementations directly.
Loading and override order¶
PluginLoader.load_plugins_with_cascade() loads plugins from three scopes:
project-local plugins in
<project>/pluginsuser plugins in
~/.niamoto/pluginsbuilt-in plugins in
src/niamoto/core/plugins
Higher-priority scopes win. If a project plugin and a built-in plugin share the same name, Niamoto keeps the project plugin and skips the lower-priority one.
The loader uses ResourcePaths so the CLI and the desktop runtime apply the
same lookup rules.
Config validation¶
Plugins validate their own parameters with Pydantic models. In practice this means:
import services validate loader config before loading data
transform services validate transformer params before computing outputs
export services validate widget and exporter config before rendering or writing files
deploy services validate platform-specific deployment settings before publishing
That contract keeps YAML errors close to the plugin that owns them.
Where plugins run¶
CLI commands call plugins through core services
FastAPI routes in the GUI call the same services
the preview engine uses transformer and widget plugins to render HTML previews
deployment commands and routes call deployer plugins
The plugin layer stays shared across entry points. The CLI, desktop app, and web UI change how users trigger work, not which plugin contracts they use.