Static Sites

There are several ways to generate static sites with Bonito. The main one is:

Bonito.export_staticFunction
export_static(html_file::Union{IO, String}, app::App)
export_static(folder::String, routes::Routes)

Exports the app defined by app with all its assets a single HTML file. Or exports all routes defined by routes to folder.

The simplest one, which also allows an interactive Revise based workflow is enabled by interactive_server:

Bonito.interactive_serverFunction
interactive_server(f, paths, modules=[]; url="127.0.0.1", port=8081, all=true)

Revise base server that will serve a static side based on Bonito and will update on any code change!

Usage:

using Revise, Website
using Website.Bonito

# Start the interactive server and develop your website!
routes, task, server = interactive_server(Website.asset_paths()) do
    return Routes(
        "/" => App(index, title="Makie"),
        "/team" => App(team, title="Team"),
        "/contact" => App(contact, title="Contact"),
        "/support" => App(support, title="Support")
    )
end

# Once everything looks goo, export the static site
dir = joinpath(@__DIR__, "docs")
# only delete the bonito generated files
rm(joinpath(dir, "bonito"); recursive=true, force=true)
Bonito.export_static(dir, routes)

For the complete code, visit the Makie website repository which is using Bonito: MakieOrg/Website

When exporting interactions defined within Julia not using Javascript, one can use, to cache all interactions:

Bonito.record_statesFunction
record_states(session::Session, dom::Hyperscript.Node)

Records the states of all widgets in the dom. Any widget that implements the following interface will be found in the DOM and can be recorded:

# Implementing interface for Bonito.Slider!
is_widget(::Slider) = true
value_range(slider::Slider) = 1:length(slider.values[])
to_watch(slider::Slider) = slider.index # the observable that will trigger JS state change
Warn

This is experimental and might change in the future! It can also create really large HTML files, since it needs to record all combinations of widget states. It's also not well optimized yet and may create a lot of duplicated messages.