Skip to Content
Course content

88: golem Framework for Production Shiny Apps

Click on the "Edit" button in the top corner of the screen to edit your slide content.

You've probably spent the last few lessons getting comfortable with Shiny's reactive programming. By now, you're likely used to the "single-file" workflow: you have an app.R, you hit "Run App," and everything works. Because of this, many developers fall into a specific trap when they move toward production.

The "It's Just a Folder" Fallacy

The most common misconception I see is the belief that "production-ready" simply means organizing your app.R into a ui.R and a server.R and putting them in a nice folder on a server. You might think, "As long as I have a requirements.txt or a list of library() calls at the top, I'm good to go."

Here is why that fails in the real world. Imagine you're building a high-stakes financial reporting dashboard for a client. You deploy your folder to a Shiny Server. Six months later, the server is updated, or a colleague installs a new version of dplyr that introduces a breaking change in how a specific join works. Suddenly, your app crashes in production, but it still works on your local machine because you're running an older version of the library. You have no version control over your dependencies, and your "app" is essentially a fragile script floating in a directory.

Thinking of Your App as a Versioned Package

This is where golem comes in. The fundamental shift is this: Stop thinking of your app as a script and start thinking of it as an R package.

When you use golem, your Shiny app is the package. This means your dependencies are tracked in a DESCRIPTION file, your functions are documented, and your app can be versioned, tested, and installed just like any other R package (like ggplot2 or dplyr). If you need to deploy your app to a new environment, you aren't copying a folder; you're installing a specific version of a package.

I've found that once you make this mental leap, the "it works on my machine" excuse disappears. You gain a formal structure that forces you to be a better engineer.

Bootstrapping the Golem Skeleton

You don't just start writing code in a golem project; you bootstrap it. I usually start by running golem::create_golem("my_app"). This generates a complete package directory.

Instead of a monolithic app.R, you'll notice a few key areas. The inst/app/ directory is where the actual Shiny logic lives, but the R/ directory is where the "heavy lifting" happens. This is a crucial distinction. If you have a complex function that calculates a Weighted Average Cost of Capital (WACC) for your financial app, that function doesn't belong in server.R. It belongs in a separate R file in the R/ folder. This makes the function unit-testable without even launching the Shiny UI.

Breaking the Monolith with Modules

One of the most powerful features of golem is how it encourages the use of Shiny modules. In a standard app, your server function often becomes a "thousand-line monster" where every input ID is globally scoped, leading to inevitable naming collisions (like having two different input$date_range variables).

With golem::add_module(), you can carve your app into isolated pieces. For our financial dashboard, you might have a mod_ticker_selection module and a mod_performance_chart module. Each module has its own namespace, meaning they can't accidentally interfere with each other. I personally refuse to build any app larger than two pages without modules; otherwise, the cognitive load of tracking reactive values becomes unbearable.

# To add a module in golem, you'd use:
golem::add_module("performance_chart")

# This creates the UI and Server logic files automatically,
# keeping your project structure clean and predictable.

The Deployment Safety Net

Finally, golem gives you dev_docs() and tools to manage your NAMESPACE. When you're ready to deploy, you aren't just pointing a server to a file. You are building the package. If a dependency is missing from your DESCRIPTION file, the build will fail before it hits the production server. It's a safety net that saves you from the 3:00 AM "production is down" phone call.




📋 Practical Task

Building a Modular Patient Vital Signs Framework

Instead of building a full app, your task is to initialize the architectural skeleton of a production-grade medical dashboard using the golem philosophy. You will simulate the process of moving from a script to a package structure.

  1. Install the golem package if you haven't already.
  2. Use golem::create_golem("PatientVitals") to create the project structure.
  3. Identify three distinct functional areas of a medical dashboard (e.g., patient_search, heart_rate_monitor, and medication_log). Use golem::add_module() to create these three modules.
  4. Create a standalone helper function in the R/ directory called calculate_bmi() that takes weight and height as arguments. Ensure this function is a standard R function, not a reactive Shiny expression.
  5. Open the DESCRIPTION file and manually add tidyverse and lubridate to the Imports: section.
  6. Run golem::document() to update the documentation and NAMESPACE.

Success Criteria: You have a package directory where the Shiny UI/Server logic is separated from the business logic (the BMI function), dependencies are formally declared in the DESCRIPTION file, and the app is split into three distinct, namespaced modules.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.