How to Create Multiple Pages Dashboards with R Shiny
Using bs4Dash to create an R Shiny dashboard with multiple pages in a sidebar
Coders!
Would you like to know how to create multiple pages dashboards using R Shiny?
In this tutorial you will learn how to:
create multiple pages using the bs4Dash R package;
build a fully customized sidebar with a logo and different categories of texts;
add a footer in your R Shiny dashboards;
change the theme and colors using Bootstrap 4;
and more…
Watch the video now:
In this tutorial, you’ll learn how to create a dashboard with multiple tabs that function as different pages. While Shiny applications are technically single-page applications, we can create the illusion of multiple pages using tabs and navigation elements.
Required Packages
To create a dashboard with multiple pages, you’ll need to install the shiny package (if you haven’t already) and the bs4Dash package developed by David Granjon. Let’s start by installing and loading these packages:
# Install R packages if not installed
if (!require(shiny)) install.packages("shiny")
if (!require(bs4Dash)) install.packages("bs4Dash")Creating an Empty Skeleton
Let’s begin with an empty skeleton to understand the basic structure of a bs4Dash application:
# Empty skeleton
library(shiny)
library(bs4Dash)
ui <- dashboardPage(
title = "Basic Dashboard",
header = dashboardHeader(),
sidebar = dashboardSidebar(),
controlbar = dashboardControlbar(),
footer = dashboardFooter(),
body = dashboardBody()
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)This creates a basic dashboard with an empty sidebar. If you’re not familiar with Shiny’s structure (UI, server, and the interaction between them), I recommend checking out my previous videos in this series.
Understanding the Dashboard Structure
The dashboardPage() function is the main container for your bs4Dash application. It accepts several arguments:
header: The top navigation bar
sidebar: The left navigation panel
controlbar: An optional right sidebar
footer: The bottom section
body: The main content area
For this tutorial, we’ll focus primarily on the user interface (UI) since our server function remains empty - we’re concentrating on layout and navigation rather than reactive functionality.
Building a Complete Dashboard
Now let’s create a full example with multiple pages. Here’s the complete code that demonstrates all the key concepts:
# Full example
ui <- dashboardPage(
title = "Basic Dashboard",
header = dashboardHeader(
title = dashboardBrand(
title = "bs4Dash",
color = "primary",
href = "https://felixanalytix.com",
image = "https://felixanalytix.com/about/image-profile.jpg",
),
skin = "light",
status = "white"
),
sidebar = dashboardSidebar(
skin = "light",
status = "primary",
elevation = 3,
sidebarUserPanel(
image = NULL,
name = "Welcome Onboard!"
),
sidebarMenu(
sidebarHeader("Header 1"),
menuItem(
"Item 1",
tabName = "item1",
icon = icon("sliders")
),
menuItem(
"Item 2",
tabName = "item2",
icon = icon("chart-simple")
)
)
),
footer = dashboardFooter(
left = p("Download the R code: ", a(
href = "https://felixanalytix.com",
target = "_blank", "felixanalytix.com"
))
),
body = dashboardBody(
tabItems(
tabItem(
tabName = "item1",
fluidRow(
lapply(1:3, FUN = function(i) {
sortable(
width = 4,
p(class = "text-center", paste("Column", i)),
lapply(1:2, FUN = function(j) {
box(
title = paste0("I am the ", j, "-th card of the ", i, "-th column"),
width = 12,
"Click on my header"
)
})
)
})
)
),
tabItem(
tabName = "item2",
box(
title = "Card with charts",
width = 9
)
)
)
)
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)Key Components Explained
Header Configuration
The dashboardHeader() creates the top navigation bar. Key features include:
title: Uses
dashboardBrand()to create a clickable logo/titlecolor: “primary” gives it a blue color (Bootstrap default)
href: Makes the title clickable and directs to your website
skin: “light” provides a light theme (you can also use “dark”)
Sidebar Navigation
The dashboardSidebar() contains your navigation menu:
status: Controls the color scheme (primary = blue)
sidebarUserPanel(): Adds a welcome message or user info
sidebarMenu(): Contains the navigation items
Creating Multiple Pages
The key to creating multiple pages lies in the connection between menuItem() in the sidebar and tabItem() in the body:
menuItem(): Each menu item needs a unique
tabNametabItem(): Each tab content must have a matching
tabName
This correspondence is crucial - the tabName in your menuItem() must exactly match the tabName in your tabItem().
Bootstrap Integration
The bs4Dash package leverages Bootstrap CSS framework, which provides:
Predefined color schemes (primary, secondary, warning, danger, info)
Consistent styling across components
Easy theme customization
Instead of hard-coding colors, you can use Bootstrap’s semantic color names, making it easy to change your entire app’s color scheme by modifying just the theme.
HTML Structure in R
You might notice that functions are nested within other functions throughout the code. This mimics HTML’s tree-like structure where elements are nested within parent elements. This is necessary because our R code is ultimately generating HTML, CSS, and JavaScript for the web browser.
Adding Content to Your Pages
Each tabItem() can contain any Shiny UI elements:
boxes: For organizing content
fluidRow(): For responsive layouts
Charts, tables, inputs: Any interactive elements
Conclusion
You now have the foundation for creating multi-page dashboards using bs4Dash. This approach gives you a sidebar-based navigation system, which is different from traditional Shiny applications that typically use tabs at the top of the page.
The key takeaways are:
Use
dashboardPage()as your main containerCreate navigation with
menuItem()in the sidebarMatch
tabNamebetween menu items and tab contentLeverage Bootstrap colors for consistent theming
Understand that nested functions mirror HTML structure
In future tutorials, we’ll explore how to customize these cards and add interactive functionality to make your dashboards even more powerful.

