Shiny for R
A Shiny app has a ui object (or function), a server(input, output, session) function, and shinyApp(ui, server) to run them together. The reactive graph is the engine: reading a reactive source (input$x, a reactive(), a reactiveVal()) inside a reactive context registers a dependency, so changing that source re-runs everything that read it — you never call outputs or schedule updates yourself.
This skill is an index. Find your task below and read the linked reference file before writing code for that area. Read the one or two references your task actually touches, not all of them.
Not every corner of Shiny has a reference here — plain inputs (selectInput(), actionButton(), ...), deployment, and app performance tuning are not covered. For those, work from your own knowledge of the package and its help pages.
Foundations
| Topic | Use when | Reference | |
|---|
| Reactivity | A value should recompute or an output update as inputs change; choosing between reactive()/observe()/observeEvent(); req(), isolate(), bindEvent(), timers, polling | references/reactivity.md | |
| Modules | A reusable, repeatable UI+server component; avoiding input/output id collisions across copies | references/modules.md | |
| Session lifecycle | Per-session cleanup (onSessionEnded()), flush hooks, unhandled errors, per-session vs app-level scope, session$userData | references/session-lifecycle.md | |
Async
| Topic | Use when | Reference | |
|---|
| Async | Returning a promises::promise from a render/observer so R keeps serving other sessions during slow I/O | references/async.md | |
| Extended tasks | Running slow work in a background process while the session that started it stays fully interactive; task buttons | references/extended-tasks.md | |
Dashboard building
| Topic | Use when | Reference | |
|---|
| Dashboard design | Turning a dataset or brief into a polished analytical dashboard; information hierarchy, shared filters, responsive layout, empty states, final visual/functional pass | references/dashboard-design.md | |
| Dashboard components | Composing bslib card(), value_box(), accordion(), tooltip()/popover() instead of hand-rolled div() markup | references/dashboard-components.md | |
| Layouts | Arranging a page with bslib page_sidebar(), layout_columns(), card() instead of nested fluidRow()/column() pyramids | references/layouts.md | |
Navigation & dynamic UI
| Topic | Use when | Reference | |
|---|
| Navigation | Grouping switchable content into a real tab container/navbar instead of faking tabs with buttons plus conditionalPanel() | references/navigation.md | |
| Dynamic UI | UI that must change after render — update*Input(), conditionalPanel(), renderUI()/uiOutput(), or insertUI()/removeUI() | references/dynamic-ui.md | |
Outputs
| Topic | Use when | Reference | |
|---|
| Plots | Pairing renderPlot()/plotOutput() for base/lattice/ggplot2 graphics; click/hover/brush interaction via nearPoints()/brushedPoints() | references/plots.md | |
| Tables | Choosing renderTable() (static), the deprecated renderDataTable(), or DT/reactable for sortable/searchable interactive tables | references/tables.md | |
| Files | fileInput() uploads and downloadHandler()/downloadButton() generated-file downloads | references/files.md | |
Feedback & state
| Topic | Use when | Reference | |
|---|
| Feedback | Toasts/notifications, modal dialogs, progress bars, and input validation sent from the server, typically inside observeEvent() | references/feedback.md | |
| Bookmarking | Saving/restoring app state via a shareable URL instead of a hand-built query string or custom persistence layer | references/bookmarking.md | |
Theming, assets & extending
| Topic | Use when | Reference | |
|---|
| Theming & assets | Setting bslib::bs_theme() Sass variables, thematic for plot theming, brand.yml, or adding custom CSS/JS/image assets | references/theming-assets.md | |
| Custom components | Integrating a third-party JS widget or bespoke interaction when no built-in input/output covers it | references/custom-components.md | |
Testing & observability
| Topic | Use when | Reference | |
|---|
| Testing | Verifying server-side reactive logic with testServer() without starting a real Shiny process or browser | references/testing.md | |
| Debugging | Dropping into a real R debugger (browser(), error breakpoints) instead of print()-debugging a running reactive graph | references/debugging.md | |
| OpenTelemetry | Tracing sessions, flush cycles, and reactive/observer/output executions instead of log-scraping or ad hoc timing | references/opentelemetry.md | |
| Ecosystem | Deciding whether a companion package (DT, plotly, leaflet, shinychat, shinytest2, etc.) already solves the problem before hand-rolling it | references/ecosystem.md | |