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
Module Structure: The
book.jlfile must return a moduleAbstractBook Subtype: Define a struct that inherits from
BonitoBook.AbstractBookcreate_book Function: Define a
create_book(book::BonitoBook.Book; kwargs...)function that returns your custom book instanceRendering: 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:
slideshow_example - Presentation mode with navigation
draggable_example - Rearrangeable cells
book-example - Alternative book layout
Usage
Place your notebook next to the plugin directory:
my-project/
├── my-plugin.md # Your content
└── .my-plugin-bbook/ # Your plugin
└── book.jlBonitoBook 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.