Introduction to Shiny

Mark Andrews

What is Shiny?

  • A framework for building interactive web applications in R
  • No JavaScript or HTML knowledge required
  • Applications run entirely in R, served by a local or remote server
  • The browser is the interface; R handles all computation

The three-part structure

Every Shiny application consists of exactly three parts:

  1. UI — a description of the interface the user sees
  2. Server — R code that processes inputs and produces outputs
  3. shinyApp(ui, server) — the call that creates and runs the app

The UI is a function call

ui <- fluidPage(
  sliderInput("n", "Points", min = 10, max = 500, value = 100),
  plotOutput("scatter")
)
  • fluidPage creates a responsive HTML page
  • Input functions create controls (here, a slider)
  • Output functions create placeholders (here, for a plot)
  • Input and output functions use a unique ID, usually as their first argument

The server is a function

server <- function(input, output) {
  output$scatter <- renderPlot({
    x <- rnorm(input$n)
    y <- rnorm(input$n)
    plot(x, y)
  })
}
  • input$n reads the current value of the slider named "n"
  • output$scatter assigns to the placeholder named "scatter"
  • renderPlot({...}) wraps the plotting code and makes it reactive

Reactive programming: the core idea

In a script, code runs once, top to bottom.

In Shiny:

  • Shiny monitors which inputs each output reads
  • When an input changes, every output that depends on it re-executes automatically
  • You write what to compute, not when to recompute

The reactive graph

input$n  ──►  renderPlot  ──►  output$scatter
  • Each arrow is a reactive dependency
  • Change input$n → Shiny invalidates renderPlot → it re-runs

This is the mental model you need for everything that follows.

Input–output pairs

UI function Server function Type of output
plotOutput renderPlot Plot
tableOutput renderTable Table
verbatimTextOutput renderPrint Pre-formatted text
textOutput renderText Inline text
uiOutput renderUI Dynamic UI elements

Common input widgets

  • sliderInput — draggable numeric slider
  • selectInput — dropdown menu
  • radioButtons — mutually exclusive options
  • checkboxGroupInput — multiple selections
  • textInput / numericInput — free text or number entry
  • actionButton — triggers computation on click

A first real application

ui <- fluidPage(
  sliderInput("bins", "Bins", min = 5, max = 50, value = 20),
  plotOutput("hist")
)
server <- function(input, output) {
  output$hist <- renderPlot({
    hist(rnorm(500), breaks = input$bins,
         col = "steelblue", border = "white")
  })
}
shinyApp(ui, server)

Move the slider — the histogram redraws instantly.

Why Shiny code looks unusual

  • Shiny code is declarative: you declare what each output is, not when to update it
  • The server function never “runs” in the normal sense — Shiny runs pieces of it reactively
  • Nested function calls in the UI are not evaluated immediately; they build an HTML description
  • This takes some adjustment but becomes natural quickly

Summary

  • Every app: UI + server + shinyApp
  • IDs connect UI controls to server logic
  • render* functions make outputs reactive to inputs
  • Shiny re-runs only the parts of the server that depend on changed inputs