Upgrade Bootstrap / Bootswatch in bslib
Architecture
bslib vendors Bootstrap and Bootswatch via npm, then applies a series of patch files that add bslib-specific features (semantic color functions, Shiny form support, navbar variables, etc.). The build pipeline is:
yarn installdownloads fresh upstream packages intoinst/node_modules/tools/yarn_install.Rmoves them toinst/lib/, adds vendor prefixes, validates prefixes, downsizes vendor libraries, applies all patches, and generates precompiled CSStools/main.Rrunsyarn_install.Rplus additional asset scripts (fonts, gfont info, variables article, component sass)
Version pins live in inst/package.json as npm aliases:
"bs5": "npm:bootstrap@5.3.8",
"bsw5": "npm:bootswatch@5.3.8",
Patches live in tools/patches/ and are applied alphabetically by filename
via git apply --reject --whitespace=fix. Later patches depend on earlier
ones (especially for shared files like _variables.scss).
Upgrade Workflow
Step 1: Update version pins
Edit inst/package.json to bump the target version(s). Only change the
versions being upgraded; leave others untouched.
Step 2: Run the build pipeline
Rscript tools/yarn_install.R
This script will stop with an error if any patch fails to apply. When it fails, proceed to Step 3 to fix patches, then re-run from scratch.
Step 3: Fix rejected patches
When patches fail, follow the systematic approach described in references/patch-fixing-guide.md.
Key points:
- Save clean upstream state before any patch application
- Test all patches sequentially to identify every failure (not just the first)
- Fix patches in parallel when possible (use subagents)
- Re-run
yarn_install.Rfrom scratch to verify the full sequence
Step 4: Verify the build
After yarn_install.R completes successfully, confirm:
R/versions.Rshows the new version (auto-generated by the script)- No
.rejfiles exist in the working tree - Vendor prefix validation passed (part of
yarn_install.R) - Precompiled CSS was generated in
inst/css-precompiled/
Step 5: Check for new/removed Bootswatch themes
List themes in inst/lib/bsw5/dist/ and compare with what existed before.
bootswatch_themes() dynamically reads directory names, so new themes are
picked up automatically. Check R/bs-theme-preset-bootswatch.R for any
hardcoded theme references that might need updating (e.g.,
bs3compat_navbar_defaults() has a hardcoded BS3 theme list).
Step 6: Check for redundant patches
If all patches applied cleanly, none are redundant. A patch whose changes were upstreamed would fail to apply because the old-state lines wouldn't match. Only investigate redundancy if a patch was already rejected.
Step 7: Report upstream changes and patch edits
Produce a changelog report for the user covering both Bootstrap and Bootswatch changes between the old and new versions. Research the changelogs (GitHub releases, release blog posts, and/or the CHANGELOG.md in the upstream repos) and organize changes into three tiers based on likely impact to bslib and Shiny apps:
Critical — Changes that directly affect bslib's patched files or Shiny
component rendering. Examples: Sass variable renames/removals, color-contrast()
algorithm changes, form element markup restructuring, navbar API changes,
dark mode variable changes.
Notable — Changes that affect commonly used Bootstrap features in Shiny apps but don't directly conflict with bslib patches. Examples: new utility classes, component behavior changes, accessibility improvements, new CSS custom properties, JavaScript API changes for components used in Shiny.
Minor — Bug fixes, docs changes, or changes to features rarely used in Shiny contexts. Examples: RTL fixes, print stylesheet changes, Offcanvas edge cases, carousel fixes.
After the categorized changelog, include a summary of all patch edits that
were required during Step 3, listing each modified patch file with a short
description of what changed and why (e.g., "updated context for new
$nav-underline-link-active-color variable added upstream").
Also include any new/removed Bootswatch themes (from Step 5) and any redundant patches identified (from Step 6) in this report.
Step 8: Run the full asset pipeline (if not already done)
Rscript tools/main.R
This runs yarn_install.R plus download_preset_fonts.R,
update_gfont_info.R, expand_variables_article_template.R, and
compile_component_sass.R.
Step 9: Run tests and checks
devtools::test()
devtools::check()
Expect existing snapshot tests to potentially need updating if HTML
serialization changed (whitespace-only diffs are safe to accept with
testthat::snapshot_accept()). Focus on whether any new failures appear
that are related to the Bootstrap upgrade.
Step 10: Visual verification
Test Shiny apps and bslib examples with:
- Default Bootstrap 5 theme
- Dark Bootswatch themes (Darkly, Cyborg, Slate, Superhero)
- Light Bootswatch themes (Flatly, Minty, Lux)
- Shiny form elements (checkbox, radio, selectize, sliders)
- Navbar styling
Key Files
| File | Role |
|---|---|
inst/package.json |
npm version pins |
R/versions.R |
Auto-generated version constants |
tools/yarn_install.R |
Main build script (~760 lines) |
tools/main.R |
Full asset pipeline runner |
tools/patches/*.patch |
~59 patch files applied to vendored sources |
inst/lib/bs5/ |
Vendored Bootstrap 5 SCSS (patched) |
inst/lib/bsw5/ |
Vendored Bootswatch 5 SCSS (patched) |
inst/css-precompiled/ |
Pre-compiled CSS output |
R/bs-theme-preset-bootswatch.R |
Theme discovery and configuration |
Common Upstream Changes That Break Patches
- Variable value changes (e.g.,
$table-color: $whitetoinitial) - New variables added between existing ones (context line shifts)
- Removed style blocks (e.g.,
.nav-item.openremoved) - Stylelint comment additions (e.g.,
/* stylelint-disable-line */) - Sass declaration reordering for Dart Sass compatibility
color-contrast()function changes (WCAG compliance updates)