Flaxon 0.3.0 and Teloce-Py 0.3.0 are available on PyPI. Release instructions are maintained on this site; source links identify the framework snapshot. Check version and upgrade guidance.

Framework source · Markdown

Plugins

Overview

Flaxon includes a powerful plugin system that allows applications and third-party packages to extend the framework without modifying the core.

Plugins can provide:

  • Routes
  • Middleware
  • CLI commands
  • Events
  • Health checks
  • Background tasks
  • Database integrations
  • Authentication providers
  • Template extensions
  • GraphQL extensions
  • WebSocket handlers
  • Configuration defaults

Plugins can be loaded manually, automatically, or discovered from installed Python packages.


Creating a Plugin

Basic Plugin

from flaxon.plugins import Plugin

class MyPlugin(Plugin):
    name = "my-plugin"
    version = "1.0.0"
    description = "Example Flaxon plugin"

    def setup(self, app):
        @app.get("/plugin")
        async def plugin():
            return {
                "plugin": self.name,
                "version": self.version,
            }

Register the plugin:

from flaxon import Flaxon
from flaxon.plugins import PluginManager

app = Flaxon("my-app")

manager = PluginManager(app)
await manager.load_plugin(MyPlugin())

Plugin Directory

A common project layout is:

project/
│
├── app.py
│
├── plugins/
│   ├── __init__.py
│   ├── auth.py
│   ├── payments.py
│   ├── analytics.py
│   └── monitoring.py
│
└── config.py

Large plugins can use their own package:

plugins/
└── analytics/
    ├── __init__.py
    ├── plugin.py
    ├── middleware.py
    ├── routes.py
    ├── cli.py
    ├── events.py
    ├── health.py
    └── templates/

Plugin Metadata

Every plugin exposes metadata.

class AnalyticsPlugin(Plugin):

    name = "analytics"

    version = "1.2.0"

    description = "Application analytics"

    author = "Flaxon Team"

    homepage = "https://example.com"

    license = "MIT"

Plugin Lifecycle

Plugins receive lifecycle events from the framework.

class LifecyclePlugin(Plugin):

    name = "lifecycle"

    def on_load(self):
        print("Loaded")

    def setup(self, app):
        print("Setup")

    async def on_startup(self):
        print("Application started")

    async def on_shutdown(self):
        print("Application shutting down")

    def on_unload(self):
        print("Plugin unloaded")

Lifecycle order:

Load
↓

Setup
↓

Startup
↓

Running

↓

Shutdown

↓

Unload

Simple Plugins

For small plugins a helper class is available.

from flaxon.plugins import SimplePlugin

def setup(app):

    @app.get("/hello")
    async def hello():
        return {"hello": "world"}

plugin = SimplePlugin(
    "hello-plugin",
    setup,
)

Loading Plugins

Load One Plugin

manager.load_plugin(MyPlugin())

Load Multiple Plugins

manager.load_plugins(
    [
        AuthPlugin(),
        CachePlugin(),
        AnalyticsPlugin(),
    ]
)

Load From Directory

await manager.load_plugins_from_path("plugins")

Load From Python Module

await manager.load_plugins_from_module(
    "myproject.plugins"
)

Load Everything

await manager.load_all_plugins()

Plugin Discovery

Flaxon can automatically discover plugins installed into Python.

manager.auto_discover()

Discovered plugins are loaded in dependency order.


Plugin Dependencies

Plugins can depend on one another.

class DatabasePlugin(Plugin):

    name = "database"

    provides = [
        "database"
    ]
class AuthPlugin(Plugin):

    name = "auth"

    requires = [
        "database"
    ]

Flaxon validates dependencies before loading plugins.

If a dependency is missing, startup fails with a clear error message.


Optional Dependencies

class MetricsPlugin(Plugin):

    optional = [
        "redis",
        "prometheus",
    ]

The plugin still loads if optional dependencies are unavailable.


Plugin Configuration

Plugins can read application configuration.

class MailPlugin(Plugin):

    def setup(self, app):

        self.host = app.config.get(
            "MAIL_HOST"
        )

        self.port = app.config.get(
            "MAIL_PORT",
            25,
        )

Plugin State

Plugins can store shared application state.

class CachePlugin(Plugin):

    def setup(self, app):

        app.state.cache = {}

Later:

cache = app.state.cache

Plugin Routes

class BlogPlugin(Plugin):

    def setup(self, app):

        @app.get("/blog")
        async def posts():
            return []

Plugin Middleware

from flaxon.middleware import Middleware

class HeaderMiddleware(Middleware):

    async def __call__(self, scope, receive, send):

        async def wrapper(message):

            if message["type"] == "http.response.start":
                headers = list(message["headers"])
                headers.append(
                    (
                        b"x-plugin",
                        b"enabled",
                    )
                )
                message["headers"] = headers

            await send(message)

        await self.app(scope, receive, wrapper)

Register:

app.add_middleware(HeaderMiddleware)

Plugin CLI Commands

from flaxon.cli import Command

class HelloCommand(Command):

    name = "hello"

    help_text = "Example command"

    def run(self, args):

        print("Hello Plugin")

Register:

app.cli.add_command(
    HelloCommand()
)

Plugin Events

Plugins can subscribe to application events.

@app.events.listener("user.created")
async def created(event):

    print(event.data)

Emit events:

await app.events.emit(
    "user.created",
    {
        "username": "alice"
    }
)

Plugin Hooks

Plugins can expose reusable hooks.

app.plugin_hooks.register(
    "before_response",
    callback,
)

Trigger:

await app.plugin_hooks.trigger_async(
    "before_response",
    response,
)

Plugin Health Checks

class RedisPlugin(Plugin):

    def setup(self, app):

        app.health.register(
            "redis",
            self.check,
        )

    async def check(self):

        return {
            "status": "healthy"
        }

Health endpoint:

GET /health

Background Tasks

Plugins can register scheduled jobs.

@app.scheduler.every(minutes=5)
async def cleanup():

    ...

Database Plugins

class PostgreSQLPlugin(Plugin):

    def setup(self, app):

        @app.on_startup
        async def connect():
            ...

        @app.on_shutdown
        async def disconnect():
            ...

Plugin Manager

manager = PluginManager(app)

manager.list_plugins()

manager.get_plugin("analytics")

manager.is_loaded("analytics")

manager.unload_plugin("analytics")

manager.reload_plugin("analytics")

Best Practices

  • Keep plugins focused on one responsibility.
  • Declare dependencies explicitly.
  • Validate configuration during setup.
  • Avoid global state.
  • Clean up resources during shutdown.
  • Use semantic versioning.
  • Document configuration options.
  • Register health checks when possible.
  • Handle startup failures gracefully.
  • Write automated tests for plugins.

Complete Example

from flaxon import Flaxon
from flaxon.plugins import PluginManager

app = Flaxon("plugin-demo")

manager = PluginManager(app)

await manager.load_plugins_from_path(
    "plugins"
)

@app.get("/")
async def home():
    return {
        "plugins": manager.list_plugins()
    }

Example response:

{
  "plugins": [
    "database",
    "authentication",
    "redis",
    "graphql",
    "analytics"
  ]
}

Use this capability in a full-stack app

Flaxon serves Python APIs and Teloce interfaces in one project. Keep validation, authorization and privileged operations on the server; components call those endpoints and present their results. Follow the full-stack lessons and Teloce integration reference to connect this capability to pages, components and application modules.