scaffold-shiny-app
About
This skill scaffolds new Shiny applications in R with three framework options: golem for production packages, rhino for enterprise applications, or vanilla for quick prototypes. It handles framework selection, project initialization, and can generate a first module. Use it when starting interactive R web apps, dashboard prototypes, or production-ready Shiny applications.
Quick Install
Claude Code
Recommendednpx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/scaffold-shiny-appCopy and paste this command in Claude Code to install this skill
Documentation
Scaffold Shiny App
Create new Shiny w/ prod-ready structure → golem|rhino|vanilla.
Use When
- New interactive R web app
- Dashboard|data explorer proto
- Prod Shiny as R pkg (golem)
- Enterprise Shiny (rhino)
In
- Required: App name
- Required: Framework (golem|rhino|vanilla)
- Optional: Module scaffold (default yes)
- Optional: renv (default yes)
- Optional: Deploy target (shinyapps.io|Posit Connect|Docker)
Do
Step 1: Choose 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 |
→ Clear decision by scope + team needs.
If err: unsure → default golem (most structure, can simplify). Vanilla only for throwaway protos.
Step 2: Scaffold
Golem
golem::create_golem("myapp", package_name = "myapp")
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
rhino::init("myapp")
Creates:
myapp/
├── app/
│ ├── js/
│ ├── logic/
│ ├── static/
│ ├── styles/
│ ├── view/
│ └── main.R
├── tests/
│ ├── cypress/
│ └── testthat/
├── .github/
├── app.R
├── dependencies.R
├── rhino.yml
└── renv.lock
Vanilla
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)
→ Project dir created w/ all scaffold files.
If err: golem → install.packages("golem"). Rhino → remotes::install_github("Appsilon/rhino"). Vanilla → ensure shiny+bslib installed.
Step 3: Configure Deps
Golem/Vanilla
# 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()
Rhino
Deps managed in dependencies.R:
# dependencies.R
library(shiny)
library(bslib)
library(DT)
→ All deps recorded in DESCRIPTION (golem) | dependencies.R (rhino) + renv-locked.
If err: renv::init() fails → check write perms. Pkg install fails → check R ver compat.
Step 4: First Module
Golem
golem::add_module(name = "dashboard", with_test = TRUE)
Creates R/mod_dashboard.R + tests/testthat/test-mod_dashboard.R.
Rhino
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)
})
})
}
Vanilla
Add to 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)
})
})
}
→ Module file w/ UI+server using proper namespacing.
If err: ensure NS(id) for all input/output IDs in UI fn. Without → IDs collide on multi-use.
Step 5: Run
# Golem
golem::run_dev()
# Rhino
shiny::runApp()
# Vanilla
shiny::runApp("app.R")
→ App launches in browser w/o errs.
If err: check R console. Common: missing pkgs (install), port in use (port = 3839), syntax errs in UI/server.
Check
- App dir has correct structure for framework
-
shiny::runApp()launches w/o errs - ≥1 module w/ UI+server
- Deps recorded (DESCRIPTION|dependencies.R)
- renv.lock captures vers
- Module uses
NS(id)for namespace isolation
Traps
- Vanilla for prod: Lacks tests, docs, deploy tooling. Use golem|rhino beyond protos.
- Missing namespace in modules: Every
inputId+outputIdmust wrapns(). Forget → silent ID collisions. - golem w/o devtools: golem apps are R pkgs. Use
devtools::load_all(),test(),document()— notsource(). - rhino w/o box: rhino uses box for imports. Don't fall back to
library()— usebox::use().
→
build-shiny-module— reusable modules w/ namespace isolationtest-shiny-app— shinytest2 + testServer() testsdeploy-shiny-app— deploy to shinyapps.io, Posit Connect, Dockerdesign-shiny-ui— bslib theming + responsivecreate-r-package— R pkg scaffold (golem apps are R pkgs)manage-renv-dependencies— detailed renv mgmt
GitHub Repository
Related Skills
executing-plans
DesignUse the executing-plans skill when you have a complete implementation plan to execute in controlled batches with review checkpoints. It loads and critically reviews the plan, then executes tasks in small batches (default 3 tasks) while reporting progress between each batch for architect review. This ensures systematic implementation with built-in quality control checkpoints.
requesting-code-review
DesignThis skill dispatches a code-reviewer subagent to analyze code changes against requirements before proceeding. It should be used after completing tasks, implementing major features, or before merging to main. The review helps catch issues early by comparing the current implementation with the original plan.
connect-mcp-server
DesignThis skill provides a comprehensive guide for developers to connect MCP servers to Claude Code using HTTP, stdio, or SSE transports. It covers installation, configuration, authentication, and security for integrating external services like GitHub, Notion, and custom APIs. Use it when setting up MCP integrations, configuring external tools, or working with Claude's Model Context Protocol.
web-cli-teleport
DesignThis skill helps developers choose between Claude Code Web and CLI interfaces based on task analysis, then enables seamless session teleportation between these environments. It optimizes workflow by managing session state and context when switching between web, CLI, or mobile. Use it for complex projects requiring different tools at various stages.
