Create a Plugin

In this tutorial, you’ll learn how to develop and register a simple plugin for SmallBlock CMS. Plugins extend the system with reusable, modular functionality — without modifying the core application.

You’ll build a “Quote of the Day” plugin that exposes a custom template tag and renders a random quote on any page.

Before You Begin

Make sure you have:

  • A working SmallBlock CMS project from Build Your First Site.

  • Basic familiarity with Python functions and modules.

  • Access to your project directory.

How Plugins Work

SmallBlock loads plugins by scanning the plugins/ directory in your project. Any package containing a plugin.py file with a register(app) function is automatically discovered and initialized.

The following diagram shows the plugin lifecycle:

digraph G {
    rankdir=LR;
    node [shape=box, style="rounded,filled", fillcolor="#eef3f8"];

    A [label="Plugin Directory\nplugins/quote_of_the_day/"];
    B [label="plugin.py\n(register function)"];
    C [label="SmallBlock Startup"];
    D [label="Plugin Registered\nTemplate Tag Available"];

    A -> B -> C -> D;
}

Step 1 — Create the Plugin Directory

Inside your project, create a new plugin folder:

cd mysite
mkdir -p plugins/quote_of_the_day
cd plugins/quote_of_the_day

Create an empty __init__.py file so Python treats this directory as a package:

touch __init__.py

Verify

  • plugins/quote_of_the_day/ exists

  • __init__.py is present

  • No errors occur when importing the package:

    python3 -c "import plugins.quote_of_the_day"
    

Step 2 — Write the Plugin Logic

Create plugin.py inside your plugin folder:

import random

QUOTES = [
    "The only way to do great work is to love what you do. — Steve Jobs",
    "In the middle of difficulty lies opportunity. — Albert Einstein",
    "What you do speaks so loudly that I cannot hear what you say. — Ralph Waldo Emerson",
]

def get_quote():
    """Return a random quote."""
    return random.choice(QUOTES)

def register(app):
    """Register the plugin with SmallBlock."""

    @app.template_tag("quote_of_the_day")
    def quote_of_the_day_tag():
        return get_quote()

    app.logger.info("Plugin 'Quote of the Day' registered.")

This plugin:

  • Defines a list of sample quotes

  • Selects one at random

  • Exposes a template tag: {% quote_of_the_day %}

Verify

You can manually test the module:

python3 -c "from plugins.quote_of_the_day.plugin import get_quote; print(get_quote())"

Step 3 — Add a Template

Create quote_of_the_day.html in the same directory:

<div class="quote">
    <em>{{ quote_of_the_day }}</em>
</div>

This provides a reusable rendering snippet, though template tags can also return plain strings.

Note

If your plugin returns HTML, you can also do:

return app.render_template("quote_of_the_day.html", quote_of_the_day=get_quote())

Step 4 — Enable the Plugin

Open your project’s plugin configuration file (usually config/settings.ini or config/plugins.ini):

[plugins]
enabled =
    quote_of_the_day

Restart the development server:

smallblock runserver

Verify

You should see a startup message:

Plugin 'Quote of the Day' registered.

Step 5 — Use the Plugin in a Template

Open a layout or page template (e.g., templates/base.html) and insert:

<aside>
    <h3>Quote of the Day</h3>
    <p>{% quote_of_the_day %}</p>
</aside>

Reload your page to see the random quote.

Troubleshooting

Plugin not loading?

  • Check the folder name: it must match the entry in enabled =.

  • Ensure plugin.py contains a register(app) function.

  • Review logs:

    smallblock logs
    

Template tag error?

  • Confirm the tag name matches exactly: quote_of_the_day.

  • Make sure the plugin is enabled before the server starts.

Template not rendering?

  • Verify your template file is located in the plugin directory, or pass the correct path to render_template() if using partials.

Next Steps

Continue extending your project with: