How to Create a BonitoBook Plugin

Create custom book formats that transform how your markdown notebooks are rendered and behave.

Basic Structure

BonitoBook plugins are directories with the pattern .name-bbook/ (per-file) or .bbook/ (shared) containing a book.jl file that returns a module:

                                          .my-plugin-bbook/        # or .bbook/ for shared configs
├── book.jl              # Must return a module
├── include.jl           # Will run any code included here
├── style.jl             # custom styling
├── ai/                  # Optional AI configs (lazy-loaded)
├── data/                # Optional data files
└── meta.toml            # Version tracking (auto-created)
                                        

Minimal Example

book.jl - return a module with a custom book type and create_book function:

Alternatively, just use an existing module:

Key Requirements

  1. Module Structure: The book.jl file must return a module

  2. AbstractBook Subtype: Define a struct that inherits from BonitoBook.AbstractBook

  3. create_book Function: Define a create_book(book::BonitoBook.Book; kwargs...) function that returns your custom book instance

  4. Rendering: Implement Bonito.jsrender(session::Session, your_book::YourBookType) for custom display logic

Adding Styles

BonitoBook automatically loads style.jl from your plugin folder. The file is lazy-loaded from a template if not present, so you only create it when you need custom styling.

Simple Approach: Customize with generate_style()

Use the built-in generate_style() function with 70+ customization parameters:

Advanced Approach: Combine Base + Custom CSS

For complete control, combine the base style with your custom CSS:

Scoping Styles to Your Plugin

Use higher-specificity selectors to scope styles to your plugin. The slideshow example wraps everything in .presentation-themed-slideshow:

Important: The style.jl file must return a Styles object (or something that can be rendered as styles).

See the slideshow_example for a complete real-world example.

Examples

See existing plugins for reference:

Usage

Place your notebook next to the plugin directory:

                                          my-project/
├── my-plugin.md              # Your content
└── .my-plugin-bbook/        # Your plugin
    └── book.jl
                                        

BonitoBook automatically detects and uses the plugin. You can also pass plugin-specific arguments:

The Book constructor arguments ( folder, replace_style, all_blocks_as_cell) are handled automatically, while any additional kwargs are forwarded to your plugin's create_book function.

You can also use Book/ book(file; folder=plugin_folder) to use a different bonitobook folder for a notebook file. This will likely get more streamlined in the future, making it easier to share plugins with the community.