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;
}](../_images/graphviz-65cd77f09418b98ae10073da1fb5e62448657a20.png)
—
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__.pyis presentNo 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.pycontains aregister(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:
Extend the Toolbar — add interactive editor tools.
Using Template Tags — pass dynamic data to templates.
Building a Custom Theme — create your site’s look and feel.