
These slides modified from https://github.com/dime-wb-trainings/shiny-training
Shiny is a web application framework for R that allows you to turn analyses into interactive web apps — all in R.
Why use it?
A Shiny app has two core components:
Apps are served to users via a host and port. The R session running the server reacts to user actions, computes results, and sends them back.
Client: The web browser where the user interacts with the app
Host:Port: Shiny app is served at an IP (host) and port
Server: Runs R session to monitor inputs and respond with outputs
Step-by-step instructions:
5. Choose Single File option when prompted:
6. Name your folder and click OK
7. Click Run App in the top-right corner
8. 🎉 You’re running your first Shiny app!
ui — User Interface
Layout elements
fluidPage() is the container for the app interface, the layout in which your content is. This is the most common, but there are other types of layouts. Check hereui — User Interface
Layout elements
sidebarLayout() splits the layout into sidebar (sidebarPanel()) and main area (mainPanel()). This is also optional.ui — User Interface
Page content
sidebarPanel() contains one input field (sliderInput()) called “bins”. This is a slider that lets a user choose a number. As you can infer from the name, in this case, it’s the number of histogram bins.ui — User Interface
Page content
mainPanel() contains a histogram (plotOutput()), which will be defined in the server function. The name, or id, of this histogram is “distPlot”server Logic Explained ⚙️The server() function takes two arguments:
input: a reactive list of input values from the UIoutput: a reactive list where you assign render functionsReactive lists are “special” lists used in reactive programming — a way to make your app automatically update outputs when inputs change.
server Logic Explained ⚙️Let’s take a look at reactivity inside a simple server( ):
renderFunction: A function like renderPlot(), renderTable(), etc. used to render an output (a plot, a table…)outputId: Identifies the rendered output in the output list (output$) for the UIvalue every time the input field referenced by inputID in the input list changes.server Logic Explained ⚙️In our case:
the server contains the logic to create the histogram distPlot in the output list (output$), using the render function renderPlot().
distPlot depends on one user input (input$bins), which pulls the number from the slider input in the UI.

➡️️ Result: the histogram updates as the slider moves!
Remember these connections?
| UI | Server |
|---|---|
plotOutput("distPlot") |
output$distPlot <- renderPlot() |
sliderInput("bins", ...) |
input$bins |
Shiny apps are built by connecting inputs (from the UI) to outputs (rendered in the server).
| Part | Role | Examples |
|---|---|---|
ui |
Define layout and inputs/outputs | sliderInput(), plotOutput() |
server |
Logic to render outputs based on inputs | renderPlot(), renderText() |
🔁 Reactivity connects them:
input$... pulls values from UI controlsoutput$... <- render...() generates dynamic contentinput and output behave like reactive lists — not regular R lists, but special objects in Shiny.input$bins = 5.input list — and any render function using it will re-execute.output$distPlot <- renderPlot({ ... input$bins ... }) updates instantly.Together, input, output, and render*() functions form the reactive backbone of your app.
Shiny includes many built-in widgets to capture user input:
| Widget | Purpose | Example Use |
|---|---|---|
numericInput() |
Enter a number | Age, price |
sliderInput() |
Select from a range | Histogram bins |
selectInput() |
Choose from a list | Country selector |
radioButtons() |
Choose one option | Plot type |
textInput() |
Enter text | Comments, filters |
fileInput() |
Upload a file | CSV, Excel |
actionButton() |
Trigger an action manually | Run, Submit |
📚 See the full gallery: ➡️ Shiny Widgets Gallery
#ca8dfd (a shade of purple)After your modifications the app should look like this:
Before you close the app, check the R console. You’ll see something like:
🔍 What it means: - 127.0.0.1 refers to your local machine (“localhost”) - 3827 is a random port number - You can open the app in any browser using this address
⛔ While the app is running: - The R console is blocked (no new commands allowed) - A stop sign appears in the RStudio toolbar
🛑 To stop the app: - Click the stop sign icon - Press Esc (or Ctrl + C in terminal) - Close the Shiny app window
For both:
Push-button publishing from RStudio or publish directly from GitHub
Request Posit Connect access as a Software Request
Want to go further with Shiny? Here are some helpful resources:
🧪 Shiny Tutorial (Official Getting Started Guide) here
📘 Mastering Shiny by Hadley Wickham (Free online book) here
💡 Shiny Widgets Gallery here
🧩 Awesome Shiny Extensions (Community plugins) here
🌐 Shiny Community (Forums, discussions) here
📦 Building Web Applications (Training) here
🧱 Adding multiple objects in layout here