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 |
1---2name: shiny-for-r3description: Building, styling, testing, debugging, or observing a Shiny for R app - library(shiny), shinyApp(), runApp(). Index skill: read this, then open the linked reference for the task. Covers reactivity (reactive/observe/req/isolate/bindEvent); modules; async promises and ExtendedTask; bslib layouts, navigation, cards, value boxes, and theming (incl. thematic and brand.yml); dynamic UI; plots with click/brush interaction; tables, file upload/download; notifications, modals, progress, validation; bookmarking; custom JS components; testServer testing; debugging; OpenTelemetry; and when to reach for DT, plotly, leaflet, shinychat, or shinytest2. Use when writing or changing any Shiny for R app, especially a dashboard, or when tempted to hand-roll what the framework provides - custom HTML tables, fake tabs, polling loops, blocking reactive work, or print-debugging server state.4license: MIT5---67# Shiny for R89A Shiny app has a `ui` object (or function), a `server(input, output,10session)` function, and `shinyApp(ui, server)` to run them together. The11reactive graph is the engine: reading a reactive source (`input$x`, a12`reactive()`, a `reactiveVal()`) inside a reactive context registers a13dependency, so changing that source re-runs everything that read it — you14never call outputs or schedule updates yourself.1516This skill is an **index**. Find your task below and **read the linked17reference file before writing code** for that area. Read the one or two18references your task actually touches, not all of them.1920Not every corner of Shiny has a reference here — plain inputs21(`selectInput()`, `actionButton()`, ...), deployment, and app performance22tuning are not covered. For those, work from your own knowledge of the23package and its help pages.2425## Foundations2627| Topic | Use when | Reference |28|---|---|---|29| 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` |30| Modules | A reusable, repeatable UI+server component; avoiding input/output id collisions across copies | `references/modules.md` |31| Session lifecycle | Per-session cleanup (`onSessionEnded()`), flush hooks, unhandled errors, per-session vs app-level scope, `session$userData` | `references/session-lifecycle.md` |3233## Async3435| Topic | Use when | Reference |36|---|---|---|37| Async | Returning a `promises::promise` from a render/observer so R keeps serving other sessions during slow I/O | `references/async.md` |38| Extended tasks | Running slow work in a background process while the session that started it stays fully interactive; task buttons | `references/extended-tasks.md` |3940## Dashboard building4142| Topic | Use when | Reference |43|---|---|---|44| 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` |45| Dashboard components | Composing bslib `card()`, `value_box()`, `accordion()`, `tooltip()`/`popover()` instead of hand-rolled `div()` markup | `references/dashboard-components.md` |46| Layouts | Arranging a page with bslib `page_sidebar()`, `layout_columns()`, `card()` instead of nested `fluidRow()`/`column()` pyramids | `references/layouts.md` |4748## Navigation & dynamic UI4950| Topic | Use when | Reference |51|---|---|---|52| Navigation | Grouping switchable content into a real tab container/navbar instead of faking tabs with buttons plus `conditionalPanel()` | `references/navigation.md` |53| Dynamic UI | UI that must change after render — `update*Input()`, `conditionalPanel()`, `renderUI()`/`uiOutput()`, or `insertUI()`/`removeUI()` | `references/dynamic-ui.md` |5455## Outputs5657| Topic | Use when | Reference |58|---|---|---|59| Plots | Pairing `renderPlot()`/`plotOutput()` for base/lattice/ggplot2 graphics; click/hover/brush interaction via `nearPoints()`/`brushedPoints()` | `references/plots.md` |60| Tables | Choosing `renderTable()` (static), the deprecated `renderDataTable()`, or `DT`/`reactable` for sortable/searchable interactive tables | `references/tables.md` |61| Files | `fileInput()` uploads and `downloadHandler()`/`downloadButton()` generated-file downloads | `references/files.md` |6263## Feedback & state6465| Topic | Use when | Reference |66|---|---|---|67| Feedback | Toasts/notifications, modal dialogs, progress bars, and input validation sent from the server, typically inside `observeEvent()` | `references/feedback.md` |68| Bookmarking | Saving/restoring app state via a shareable URL instead of a hand-built query string or custom persistence layer | `references/bookmarking.md` |6970## Theming, assets & extending7172| Topic | Use when | Reference |73|---|---|---|74| 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` |75| Custom components | Integrating a third-party JS widget or bespoke interaction when no built-in input/output covers it | `references/custom-components.md` |7677## Testing & observability7879| Topic | Use when | Reference |80|---|---|---|81| Testing | Verifying server-side reactive logic with `testServer()` without starting a real Shiny process or browser | `references/testing.md` |82| Debugging | Dropping into a real R debugger (`browser()`, error breakpoints) instead of `print()`-debugging a running reactive graph | `references/debugging.md` |83| OpenTelemetry | Tracing sessions, flush cycles, and reactive/observer/output executions instead of log-scraping or ad hoc timing | `references/opentelemetry.md` |84| Ecosystem | Deciding whether a companion package (DT, plotly, leaflet, shinychat, shinytest2, etc.) already solves the problem before hand-rolling it | `references/ecosystem.md` |