Skip to main content

Recreating a shiny app

Here we demonstrate how to reproduce a basic shiny application with ambiorix: a simple app which at the click of a button fits a polynomial to randomly generated data, this is visualised with plotly.



ui <- fluidPage(
actionButton("randomize", "Randomize"),

server <- function(input, output){
output$chart <- renderPlotly({

df <- list(
x = 1:100,
y = runif(100)

model <- loess(y ~ x, data = df)
augmented <- broom::augment(model)

augmented %>%
plot_ly(x = ~x, y = ~y, type = 'scatter', mode = 'lines') %>%
add_lines(y = ~.fitted)

shinyApp(ui, server)

The ui consists of a button and the plotlyOutput.

In the server we place input$randomize in the renderPlotly function so it retriggers that expression.


One could reproduce this with ambiorix in numerous ways. It could be done à la shiny: using the websocket to send a message to the server when the plot is clicked and have the server respond with the chart configuration but we shall go a different way.

We can build an endpoint that returns the randomize loess and, in JavaScript bind the button to a function that fetches this endpoint and produces the chart.

The back can be fairly simple the homepage (/) sends an HTML file (which we'll create right after this). We also create the endpoint that generates the random data, runs loess and sends a JSON response.

# app.R

app <- Ambiorix$new()

# homepage
app$get("/", \(req, res){

app$get("/randomize", \(req, res){

df <- list(
x = 1:100,
y = runif(100)

model <- loess(y ~ x, data = df)
augmented <- broom::augment(model)

data <- list(
x = augmented[["x"]],
y = augmented[["y"]],
fitted = augmented[[".fitted"]]


Then in HTML we import plotly from the CDN in the head, add a button which runs the JavaScript function randomize() that fetches the data from the /randomize endpoint and generates the chart.

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src=""></script>
<button onclick="randomize()">Normalize</button>
<div id="chart"></div>
randomize = function(){
.then(response => response.json())
.then(data => {
var trace1 = {
x: data.x,
y: data.y,
type: 'line'

var trace2 = {
x: data.x,
y: data.fitted,
type: 'line'

var data = [trace1, trace2];

Plotly.newPlot('chart', data);