scss/_variables.scss holds about a thousand settings: colors, z-indexes, breakpoints, the breadcrumb separator, carousel timing. Older guides told you to edit it and run npm 2,036 run dist, but the next npm update wipes such edits. Write your own entry file instead and set variables before Bootstrap 2,007 's defaults load; because every Bootstrap variable is declared !default, your value wins. The example is a one-page Vite 25,978 project (Build Tools and Bundlers) with a navbar, two cards and a modal; src/main.js imports the stylesheet.
// 1. Functions first, so overrides can use tint-color(), shade-color() ...
@import "bootstrap/scss/functions";
// 2. Variable and option overrides (no !default)
$primary: #1565c0;
$font-family-sans-serif: "Inter", system-ui, sans-serif;
$border-radius: .75rem;
$enable-shadows: true;
$enable-negative-margins: true;
// 3. Required configuration
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
// 4. Map overrides: add a "brand" theme color
$theme-colors: map-merge($theme-colors, ("brand": #6a1b9a));
// 5. The rest of Bootstrap
@import "bootstrap/scss/bootstrap";npm install --save-dev vite sass
npm install bootstrap @popperjs/core
npm run build # "build": "vite build" in package.jsonvite v8.3.0 building client environment for production... ✓ 63 modules transformed. dist/index.html 1.31 kB │ gzip: 0.52 kB dist/assets/index-D2AbRJbw.css 239.01 kB │ gzip: 31.78 kB dist/assets/index-DBAio9At.js 81.03 kB │ gzip: 24.23 kB ✓ built in 3.15s
Step 5 imports functions and variables a second time, which is harmless: configuration partials print no CSS and !default keeps your values. Merging "brand" into $theme-colors makes every loop over the map generate .btn-brand, .bg-brand, .text-bg-brand and .alert-brand, while the new $primary recolors buttons, links, focus rings and form controls, including their computed hover shades. An unmodified import builds to 225 kB here, so the overrides add 14 kB. Other switches worth knowing are $enable-gradients, $enable-dark-mode: false and $enable-important-utilities: false.
The build needs the silenceDeprecations option shown in Optimizing. Its list differs from Bootstrap's Vite guide (Installing Bootstrap): Sass 1.104 22,539 reports mixed-decls as obsolete and adds an if-function warning, so read the build log whenever you upgrade Sass.