Overview

Shiny makes it easy to build web applications with Python code. It enables you to customize the layout and style of your application and dynamically respond to events, such as a button press, or dropdown selection.

Shiny applications consist of two parts: the user interface (or UI), and the server function. These are combined using a shiny.App object.

This is shown in the interactive example below.

#| standalone: true

from shiny import App, ui

# Part 1: ui ----
app_ui = ui.page_fluid(
    "Hello, world!",
)

# Part 2: server ----
def server(input, output, session):
    ...

# Combine into a shiny app.
# Note that the variable must be "app".
app = App(app_ui, server)

Notice how the UI part defines what visitors will see on their web page. Right now this is just the static text “Hello, world!”. The dynamic parts of our app happen inside the server function, which is currently empty.

Note

You can modify the example code, and then re-run it by pressing the play button on the top-right of the code pane.

Try changing the page text to "Hello, Shiny world!" and re-running the application.

In the next sections we’ll modify the UI and server to take input from a user, and display some calculations!

Adding UI inputs and outputs

The first step toward basic interactivity is to add inputs and outputs to the UI.

#| standalone: true

from shiny import App, ui

app_ui = ui.page_fluid(
    ui.input_slider("n", "Choose a number n:", 0, 100, 40),
    ui.output_text_verbatim("txt")
)

def server(input, output, session):
    ...

app = App(app_ui, server)

Note the two new UI pieces added:

  • input_slider() creates a slider.
  • output_text_verbatim() creates a field to display dynamically generated text. There’s no text yet, but we’ll add it next.

Adding server logic

Now we can add to the server function. Inside of the server function, we’ll define an output function named txt. This output function provides the content for the output_text_verbatim("txt") in the UI.

Try moving the slider below to see the text output automatically change.

#| standalone: true

from shiny import ui, render, App

app_ui = ui.page_fluid(
    ui.input_slider("n", "N", 0, 100, 40),
    ui.output_text_verbatim("txt"),
)

def server(input, output, session):
    @output
    @render.text
    def txt():
        return f"n*2 is {input.n() * 2}"

# This is a shiny.App object. It must be named `app`.
app = App(app_ui, server)

Note that inside of the server function, we do the following:

  • define a function named txt, whose output shows up in the UI’s output_text_verbatim("txt").
  • decorate it with @render.text, to say the result is text (and not, e.g., an image).
  • decorate it with @output, to say the result should be displayed on the web page.

(Soon we’ll see other kinds of render.* decorators, like render.plot.)

Finally, notice our txt() function takes the value of our slider n, and returns its valued multiplied by 2. To access the value of the slider, we use input.n(). Notice that this is a callable object (like a function) that must be invoked to get the value.

This reactive flow of data from UI inputs, to server code, and back out to UI outputs is fundamental to how Shiny works.

Reactive flow

When you moved the slider in the app above, a series of actions were kicked off, resulting in the output on the screen changing. This is called reactivity.

The diagram below shows how the updated input flows through a Shiny application.

Reactive flow of code through a Shiny application

Inputs, like our slider n, are reactive values: when they change, they automatically cause any the reactive functions that use them (like txt()) to recalculate.

Next Steps

In the following sections we’ll look more deeply into the UI, and then server logic. Then, we’ll put everything together using three example apps. While these three applications are useful on their own, we’ll look next at ways we could improve them using more advanced reactive programming concepts.

Finally, we’ll cover the best ways to run and debug Shiny applications.