Developing a Betty extension - Betty documentation

Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
View this page
Toggle table of contents sidebar

# 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.app.extension.Extension`, for example:

>     from betty.app.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:

pyproject.toml

    [project.entry-points.'betty.extensions']
    'my_package.my_module.MyExtension' = 'my_package.my_module.MyExtension'

setup.py

    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.app.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.app.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.app.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.app.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.app.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.

## Dispatching

Extensions can handle dispatched events by extending from any of the following classes:

`betty.app.extension.ConfigurableExtension`

  Enable configuration management for the extension.

`betty.app.extension.Theme`

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

`betty.app.extension.UserFacingExtension`

  Mark the extension as being suitable for end user interaction, e.g. it is not internal.

`betty.generate.Generator`

  Dispatched when the site is being generated. This is used to tell extensions when to generate their parts of the site.

`betty.gui.GuiBuilder`

  Provide a Graphical User Interface to manage the extension in the Betty Desktop application.

`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.

`betty.load.Loader`

  Dispatched when data is loaded into an ancestry. This is used to import data.

`betty.load.PostLoader`

  Dispatched after data is loaded into an ancestry. This is used to modify loaded data.