Developing a Betty extension

Extensions are Betty plugins that integrate deeply with the Betty application and have the most power to change or add functionality to your sites.

Getting started

  1. Determine where in your package you want the extension to be located. Its fully qualified name will be used as its extension name, e.g. an extension my_package.my_module.MyExtension will be named "my_package.my_module.MyExtension". This name is also used to enable the extension in project configuration files.

  2. Create a new class that extends betty.project.extension.Extension, for example:

from betty.project.extension import Extension

class MyExtension(Extension):
  pass

Congratulations! You have created your very first Betty extension. Keep reading to learn how to add functionality.

Making your extension discoverable

Making your extension discoverable means that Betty knows it’s available and can present users with the option to enable and configure your extension for their project.

Given an extension my_package.my_module.MyExtension, add the following to your extension’s Python package:

[project.entry-points.'betty.extensions']
'my_package.my_module.MyExtension' = 'my_package.my_module.MyExtension'
SETUP = {
    'entry_points': {
        'betty.extensions': [
            'my_package.my_module.MyExtension=my_package.my_module.MyExtension',
        ],
    },
}
if __name__ == '__main__':
    setup(**SETUP)

Asset management

Extensions can enable asset management to provide translations, templates, and more, by overriding betty.project.extension.Extension.assets_directory_path() to return the path on disk where the extension’s assets are located. This may be anywhere in your Python package.

from betty.project.extension import Extension

class MyExtension(Extension):
    @classmethod
    def assets_directory_path(cls) -> Path | None:
        # A directory named "assets" in the same parent directory as the current Python file.
        return Path(__file__).parent / 'assets'

Dependencies

Important

Any dependencies on other Python packages must be declared by your extension’s Python package.

Extensions have fine-grained control over which other extensions they require, and the order in which they appear in the extension dependency tree:

betty.project.extension.Extension.depends_on()

Declare required other extensions. This ensures those extensions are enabled and appear before your extension in the extension dependency tree.

betty.project.extension.Extension.comes_after()

Declare other extensions that are not required, but if they are enabled, then your extension will appear after them in the extension dependency tree.

betty.project.extension.Extension.comes_before()

Declare other extensions that are not required, but if they are enabled, then your extension will appear before them in the extension dependency tree.

Optional functionality

Extensions can optionally provide the following functionality:

betty.project.extension.ConfigurableExtension

Enable configuration management for the extension.

betty.project.extension.Theme

Mark the extension as being a theme, e.g. an extension that determines the overall look and feel of a site.

betty.html.CssProvider

Add additional CSS files to generated pages.

betty.html.JsProvider

Add additional JavaScript files to generated pages.

betty.jinja2.Jinja2Provider

Integrate the extension with Jinja2.