dlboard

dlboard official documentation

View on GitHub

Plugins

What is this

Most opinionated behavior in dlboard — where data is stored, how a chart renders, who a request is attributed to, what theme is applied — is a plugin. A plugin is any module implementing PluginProtocol (dlboard/models/_plugin.py): a single classmethod,

def plug(cls, app: Dash) -> None: ...

dlboard.serve.app.app(plugins) calls plug(app) on every plugin in the list, in order, once at startup. That’s the entire contract — there’s no base class to inherit and no registry to update by hand, just a module with a plug function.

When you’d need this

You’re building a new storage backend, chart type, auth provider, or theme, and want to know where the extension points are and how a plugin gets composed into a running app. Read the page for the specific category you’re building — storage, charts, auth, themes — this page is about the plugin mechanism itself, not any one category.

Page layout (home, project, admin, experiment, account) is deliberately not a plugin category — these modules don’t implement PluginProtocol at all, since nobody swaps out the experiment page’s tab+accordion layout the way they might swap sqlite for postgres. dlboard.serve.app.app() calls register(app) on each of the built-in pages directly and unconditionally — they’re never part of the plugins list a deployment passes in, and never touch the plug(app) mechanism this page describes. See architecture.md for where their code lives (dlboard/serve/_pages/).

How it works

Writing one. A plugin module needs a plug(app: Dash) -> None function. What it does inside is entirely up to the category: register a Flask route, set a data store on the app, register a chart type, wire a callback. Look at dlboard/plugins/themes/default.py for the smallest real example (one set_theme call, no state) before tackling a bigger category.

Registering one. Add the module to the list passed into app() — see LOCAL_DEPLOYMENT in dlboard/plugins/__init__.py for the reference bundle dlboard serve local uses. There’s no other registration step; a plugin not in that list is never loaded.

Identity, not state. Once plugged, a plugin is snapshotted as an InstalledPlugin (name + first docstring line — see InstalledPlugin.describe in dlboard/models/_plugin.py) for introspection (the admin page’s About tab lists installed plugins this way). Deliberately no reference to the plugin module/object itself is kept, so that introspection can’t reach back into a plugin’s internal state from an arbitrary callback thread.

Design boundary. The core app exposes minimal hooks for plugins to use (the Store accessors described in architecture.md); any opinionated choice within a plugin’s own category — how a chart is styled, which auth scheme resolves a user, where artifacts land on disk — belongs in the plugin, not the core.