Skip to contents

shinygenui lets you add generative UI to Shiny apps. As the app developer, you choose a fixed set of UI components and describe the arguments that each component accepts. Together, these components form a catalog. When someone asks a question in the chat panel, the model chooses components from the catalog and adds them to a canvas. It can also update or remove components as the conversation continues.

The package is similar to Vercel’s json-render and Google’s A2UI, but has a much smaller scope. It uses R, Shiny, and the deployment approaches you already use for Shiny apps. You do not need Node, another server, or schemas written by hand.

Installation

# install.packages("pak")
pak::pak("nanxstats/shinygenui")

How it works safely

  • The model calls tools instead of writing code. Each catalog entry becomes an ellmer tool with typed arguments. The model calls these tools with data. It never writes R code, and shinygenui never calls eval() or parse() on model output.
  • The catalog can reflect the current session. If you create the catalog inside the server function, its argument types can use values that are known at that point. For example, an argument can only accept names from the current dataset. If the model invents a column, validation rejects it.
  • Errors return to the model. If validation or rendering fails, the model receives an error that explains what went wrong and can try again. The Shiny session keeps running. Even if a prompt injection changes what the model asks for, it cannot make the package run code outside the catalog.

Example

Here is a complete app with a chat sidebar, a canvas, and a catalog based on mtcars. Start by asking for a plot of mpg against hp and a value box with the average mpg. Then ask the model to color the points by cylinder count. It updates the existing plot in place.

library(shiny)
library(bslib)
library(shinygenui)

ui <- page_sidebar(
  title = "mtcars explorer",
  sidebar = sidebar(width = 380, shinychat::chat_ui("chat", height = "100%")),
  genui_canvas("canvas")
)

server <- function(input, output, session) {
  catalog <- genui_catalog(genui_components_bslib(data = mtcars))
  genui_server(
    "canvas",
    catalog = catalog,
    chat = ellmer::chat_anthropic(), # Any ellmer provider works
    data = reactive(mtcars),
    chat_id = "chat",
    system_prompt = genui_prompt(catalog, context = "The data is mtcars.")
  )
}

shinyApp(ui, server)

The included components have the same interactive behavior as any other Shiny UI. For example, the histogram has a slider for the number of bins. Moving the slider redraws the plot immediately without another request to the model.

You can define your own component with genui_component():

genui_component(
  name = "value_box",
  description = "A box highlighting one summary statistic.",
  args = list(
    title = "Short label above the value.",
    column = ellmer::type_enum(names(mtcars), "Column to summarize.")
  ),
  ui = function(id, args) {
    ...
  }, # Return htmltools tags
  server = function(id, args, data) {
    ...
  } # Optional Shiny module
)

The inst/examples/ directory contains two runnable apps:

shiny::runApp(system.file("examples/01-mtcars-explorer/", package = "shinygenui"))
shiny::runApp(system.file("examples/02-layout/", package = "shinygenui"))

01-mtcars-explorer introduces the basics. 02-layout shows how to group components in rows and rebuild a canvas from its saved history with genui_replay().

Learn more

License

MIT