A floating chatbot for Shiny. Because every other ecosystem has one and R didn’t.
Python has chat widgets. JavaScript has chat widgets. R/Shiny had textInput() and a prayer.
chatbotr adds a floating chat bubble (or slide-out panel) on top of {shinychat} to any Shiny app, backed by any LLM via {ellmer}. Bring your own key.
Installation
pak::pak("freestatman/chatbotr")[!IMPORTANT] Requires
ellmer >= 0.4.0.9000, to use GitHub API as model provider: unreleased PRpakalso resolves theshinychatremote (posit-dev/shinychat) so you don’t have to think about it.
Quick start
library(shiny); library(bslib); library(chatbotr)
ui <- page_fluid(
floating_chat_ui("chat")
)
server <- function(input, output, session) {
floating_chat_server("chat", client = ellmer::chat_github(model = "gpt-5-mini"))
}
shinyApp(ui, server)Chat bubble, bottom-right corner. Click, talk, close. Dashboard unharmed.
Two flavors
| Style | UI | Server |
|---|---|---|
| Floating bubble | floating_chat_ui() |
floating_chat_server() |
| Slide-out panel | offcanvas_chat_ui() |
offcanvas_chat_server() |
Both accept any ellmer client. GitHub Copilot, OpenAI, Anthropic, Gemini — dealer’s choice.
BYOK
Let users supply their own API key at runtime:
ui <- page_fluid(
api_settings_ui("settings"),
floating_chat_ui("chat")
)
server <- function(input, output, session) {
settings <- api_settings_server("settings")
observe({
req(settings$is_configured())
floating_chat_server("chat", client = settings$client())
})
}
shinyApp(ui, server)Or set OPENAI_API_KEY in .Renviron and move on with your life.
Examples
shiny::runApp(system.file("examples/floating_chat_demo.R", package = "chatbotr"))
shiny::runApp(system.file("examples/byok_floating_chat.R", package = "chatbotr"))
shiny::runApp(system.file("examples/offcanvas_chat_demo.R", package = "chatbotr"))Browse the example source on GitHub: Floating, BYOK, Offcanvas.
Origin story
Vibe-coded across multiple AI editors — opencode, Copilot CLI, Antigravity. All three contributed. None of them asked for credit.