From agent-almanac
Scaffold Shiny apps using golem (R package), rhino (enterprise), or vanilla (prototype) structure. Handles framework selection, project initialization, and first module creation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/agent-almanac:scaffold-shiny-appThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create a new Shiny application with production-ready structure using golem, rhino, or vanilla scaffolding.
Create a new Shiny application with production-ready structure using golem, rhino, or vanilla scaffolding.
Evaluate the project requirements to select the appropriate framework:
| Framework | Best For | Structure |
|---|---|---|
| golem | Production apps shipped as R packages | R package with DESCRIPTION, tests, vignettes |
| rhino | Enterprise apps with JS/CSS build pipeline | box modules, Sass, JS bundling, rhino::init() |
| vanilla | Quick prototypes and learning | Single app.R or ui.R/server.R pair |
Expected: Clear framework decision based on project scope and team needs.
On failure: If unsure, default to golem — it provides the most structure and can be simplified later. Vanilla is only appropriate for throwaway prototypes.
golem::create_golem("myapp", package_name = "myapp")
This creates:
myapp/
├── DESCRIPTION
├── NAMESPACE
├── R/
│ ├── app_config.R
│ ├── app_server.R
│ ├── app_ui.R
│ └── run_app.R
├── dev/
│ ├── 01_start.R
│ ├── 02_dev.R
│ ├── 03_deploy.R
│ └── run_dev.R
├── inst/
│ ├── app/www/
│ └── golem-config.yml
├── man/
├── tests/
│ ├── testthat.R
│ └── testthat/
└── vignettes/
rhino::init("myapp")
This creates:
myapp/
├── app/
│ ├── js/
│ ├── logic/
│ ├── static/
│ ├── styles/
│ ├── view/
│ └── main.R
├── tests/
│ ├── cypress/
│ └── testthat/
├── .github/
├── app.R
├── dependencies.R
├── rhino.yml
└── renv.lock
Create app.R:
library(shiny)
library(bslib)
ui <- page_sidebar(
title = "My App",
sidebar = sidebar(
sliderInput("n", "Sample size", 10, 1000, 100)
),
card(
card_header("Output"),
plotOutput("plot")
)
)
server <- function(input, output, session) {
output$plot <- renderPlot({
hist(rnorm(input$n), main = "Random Normal")
})
}
shinyApp(ui, server)
Expected: Project directory created with all scaffolding files.
On failure: For golem, ensure the golem package is installed: install.packages("golem"). For rhino, install from GitHub: remotes::install_github("Appsilon/rhino"). For vanilla, ensure shiny and bslib are installed.
# Initialize renv
renv::init()
# Add core dependencies
usethis::use_package("shiny")
usethis::use_package("bslib")
usethis::use_package("DT") # if using data tables
usethis::use_package("plotly") # if using interactive plots
# Snapshot
renv::snapshot()
Dependencies are managed in dependencies.R:
# dependencies.R
library(shiny)
library(bslib)
library(DT)
Expected: All dependencies recorded in DESCRIPTION (golem) or dependencies.R (rhino) and locked with renv.
On failure: If renv::init() fails, check write permissions. If packages fail to install, check R version compatibility.
golem::add_module(name = "dashboard", with_test = TRUE)
This creates R/mod_dashboard.R and tests/testthat/test-mod_dashboard.R.
Create app/view/dashboard.R:
box::use(
shiny[moduleServer, NS, tagList, h3, plotOutput, renderPlot],
)
#' @export
ui <- function(id) {
ns <- NS(id)
tagList(
h3("Dashboard"),
plotOutput(ns("plot"))
)
}
#' @export
server <- function(id) {
moduleServer(id, function(input, output, session) {
output$plot <- renderPlot({
plot(1:10)
})
})
}
Add module functions to a separate file R/mod_dashboard.R:
dashboardUI <- function(id) {
ns <- NS(id)
tagList(
h3("Dashboard"),
plotOutput(ns("plot"))
)
}
dashboardServer <- function(id) {
moduleServer(id, function(input, output, session) {
output$plot <- renderPlot({
plot(1:10)
})
})
}
Expected: Module file created with UI and server functions using proper namespacing.
On failure: Ensure the module uses NS(id) for all input/output IDs in the UI function. Without namespacing, IDs will collide when the module is used multiple times.
# Golem
golem::run_dev()
# Rhino
shiny::runApp()
# Vanilla
shiny::runApp("app.R")
Expected: Application launches in the browser without errors.
On failure: Check the R console for error messages. Common issues: missing packages (install them), port already in use (specify a different port with port = 3839), or syntax errors in UI/server code.
shiny::runApp() launches without errorsNS(id) for proper namespace isolationinputId and outputId in a module UI must be wrapped with ns(). Forgetting this causes silent ID collisions.devtools::load_all(), devtools::test(), and devtools::document() — not source().library() calls — use box::use() for explicit imports.build-shiny-module — create reusable Shiny modules with proper namespace isolationtest-shiny-app — set up shinytest2 and testServer() testsdeploy-shiny-app — deploy to shinyapps.io, Posit Connect, or Dockerdesign-shiny-ui — bslib theming and responsive layout designcreate-r-package — R package scaffolding (golem apps are R packages)manage-renv-dependencies — detailed renv dependency managementnpx claudepluginhub pjt222/agent-almanacDesigns Shiny app UIs with bslib theming, responsive grids, value boxes, cards, and custom CSS/SCSS. Covers page layouts, accessibility, and brand consistency.
Builds modern Shiny dashboards using bslib (Bootstrap 5) with page layouts, cards, value boxes, navigation, sidebars, and theming. Replaces legacy Shiny UI patterns.
Scaffolds boilerplate for APIs (FastAPI, Express), web apps (Next.js, Nuxt, SvelteKit), CLI tools, libraries, monorepos with best-practice stacks and directory structures.