Overview
Welcome to the learn Shiny overview! Here we’ll introduce Shiny’s capabilities and link to articles where you can learn more. In the next article, we’ll cover more user interface (UI) components by building this dashboard:
Many examples on this site have a code editor for modifying the source code for a Shiny app (which runs entirely in the browser, thanks to shinylive). If you’d like to run any examples locally, first install and run Shiny locally, then copy/paste relevant code into the app.py
file (created by shiny create
).
Basics
Shiny apps typically start with input components to gather information from a user, which are then used to reactively render output components. Here’s a basic example that displays a slider’s value as formatted text.
This example demonstrates the basic mechanics behind Shiny apps:
- Inputs are created via
ui.input_*()
functions.- The first argument is the input’s
id
, which is used to read the input’s value.
- The first argument is the input’s
- Outputs are created by decorating a function with
@render.*
.- Inside a
render
function,input
values can be read reactively. - When those
input
values change, Shiny knows how to minimally re-render output.
- Inside a
- This example happens to use
shiny.express
which, compared to core Shiny, reduces the amount of code required.
Components
Shiny includes many useful user interface (ui
) components for creating inputs, outputs, displaying messages, and more. For brevity sake, we’ll highlight just a few output and layout components here, but for a more comprehensive list, see the components gallery.
Outputs
Shiny makes it easy to create dynamic plots, tables, and other interactive widgets. All you need to do is apply a @render
decorator to a function that returns a suitable object. Shiny includes a wide variety of these decorators in its render
module, but Shiny extensions like shinywidgets
provide additional decorators for rendering other kinds of outputs, like Jupyter Widgets.
To include a plot in an application, apply @render.plot
to a function that creates a matplotlib visual. Note that packages like seaborn, plotnine, pandas, etc., are all compatible (as long as they create a matplotlib visual).
Apply @render.data_frame
to any code that returns a pandas or polars DataFrame for a basic table. For more sophisticated tables, you can use render.DataGrid
to add things like filters to your table.
See the Jupyter Widgets article for more information on rendering Jupyter Widgets in Shiny.
Many other awesome Python packages provide widgets that are compatible with Shiny. In general, you can render them by applying the @render_widget
decorator.
import shiny.express
from shinywidgets import render_widget
@render_widget
def widget():
# Widget code goes here
...
Layouts
Shiny provides a full suite of layout components which help with arranging multiple inputs and outputs in a variety of ways. As seen below, with shiny.express
, layout components (e.g., ui.sidebar()
) can be used as context managers to help with nesting and readability.
Shiny also integrates well with Quarto, allowing you to leverage its web-based output formats (e.g., dashboards) in combination with Shiny outputs and reactivity.
Reactivity
Shiny uses something called transparent reactivity to automatically infer relationships between components, and minimally re-render as needed when dependencies change.1 As a result, apps naturally retain performance as they grow in size, without workarounds like caching or memoization. All Shiny apps are also built on the same small set of reactive foundations, each of which are simple and easy to learn, but can be combined in novel ways to create seriously sophisticated and performant apps.
To demonstrate how Shiny minimally re-renders, consider the following app which contains two different plots, each of which depends on a different input. When the first input changes, Shiny knows to only re-render the first plot, and vice versa.
Shiny also knows when outputs are visible or not, and so, will only call render
functions when needed. For example, in the app below, the table
function doesn’t get called until the “Table” page is selected.
For a more in-depth look at reactivity, check out the reactivity article.
Starter templates
Once you’ve installed Shiny, the shiny create
CLI command provides access to a collection of useful starter templates. This command walks you through a series of prompts to help you get started quickly with a helpful example. One great option is the dashboard template, which can be created with:
shiny create --template dashboard
See the workflow section for more information developing Shiny apps locally. Also keep in mind you can develop apps in the browser using the playground.
Extensible foundation
Shiny is built on a foundation of web standards, allowing you to incrementally adopt custom HTML, CSS, and/or JavaScript as needed. In fact, Shiny UI components themselves are built on a Python representation of HTML/CSS/JavaScript, which you can see by printing them in a Python REPL:
>>> from shiny import ui
>>> ui.input_action_button("btn", "Button")
<button class="btn btn-default action-button" id="btn" type="button">Button</button>
And, since UI is HTML, you can gently introduce HTML/CSS/JavaScript as needed in your apps to customize without having to learn complicated build tooling and frameworks. However, if you’re versed in web programming, you can also use Shiny to create custom components that leverage your favorite JavaScript framework from Python.
Next steps
Next, we’ll learn more about Shiny components and layouts by making a dashboard.