Adding reactive pages
In Genie Framework, the Stipple.jl
package implements a reactive UI layer that enables dynamic interactivity with the UI. This is useful for building apps that require real-time updates, such as dashboards, data visualizations, and simulations.
We refer to this type of interfaces as reactive, since the app instantly reacts to a user action by executing some code and updating the UI. All without having to reload the page. This is made possible by the Javascript code provided by Stipple.jl
that enables two-way synchronization between the browser and the server.

There are several possible patterns for apps with reactive pages. For more details on building reactive apps, see the Your first dashboard guide and the docs.
Single app module with multiple pages
When building apps without too much logic, it might be sufficient to keep it all in a single module even if there's multiple pages. You just need to define additional routes for each page as in this example, which uses the StatisticAnalysis
module defined here:
module App
using GenieFramework
#import your Julia code
using .StatisticAnalysis
@genietools
# Implement reactive code
@app begin
@in N = 0
@out m = 0.0
@out name = "John"
@onchange N begin
m = calc_mean(gen_numbers(N))
end
end
# Define the UI for each page
index() = [h1("Welcome {{name}}!"), a(href="/form")]
function formui()
cell([
textfield("How many numbers?", :N),
p("The average of {{N}} random numbers is {{m}}"),
])
end
# Define the routes
@page("/", index)
@page("/form", formui)
end
Alternatively, you can place the UI code in a separate file and include it as
@page("/", "ui.jl")
cell([
textfield("How many numbers?", :N),
p("The average of {{N}} random numbers is {{m}}"),
])
Multiple app modules
If each page performs different functions, for instance a dashboard page and a another page with a configuration panel, you can implement them in separate logic modules. Then, simply include them with a @page
route in the main app module as in this example:
module App
using GenieFramework
include("Index.jl")
include("Form.jl")
using .Index
using .Form
@page("/", Main.App.Index.ui, DEFAULT_LAYOUT(), Main.App.Index)
@page("/form", Main.App.Form.ui, DEFAULT_LAYOUT(), Main.App.Form)
end
module Index
using GenieFramework
@app begin
@out name = "John"
end
function ui()
h1("Welcome {{name}}!"),
end
end
module Form
using GenieFramework
using .StatisticAnalysis
@app begin
@in N = 0
@out m = 0.0
@onchange N begin
m = calc_mean(gen_numbers(N))
end
end
function ui()
cell([
textfield("How many numbers?", :N),
p("The average of {{N}} random numbers is {{m}}"),
])
end
end