Good folder structure makes Bootstrap projects easier to maintain. Here's what works across three common project types.
Simple HTML + CSS Project
For a static site without a build tool:
my-project/
├── index.html
├── about.html
├── contact.html
├── css/
│ ├── custom.css ← your styles (after Bootstrap)
│ └── custom.min.css ← optional minified version
├── js/
│ └── app.js ← your JavaScript
└── images/
├── logo.svg
└── hero.jpg
In your HTML, load order matters — Bootstrap first, your CSS after:
<head>
<!-- Bootstrap CSS first -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Your overrides after -->
<link href="css/custom.css" rel="stylesheet">
</head>
<body>
<!-- content -->
<!-- Bootstrap JS before closing body -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Your JS after -->
<script src="js/app.js"></script>
</body>
Vite + Sass Project
The recommended setup for projects that need custom Bootstrap theming:
my-project/
├── index.html
├── package.json
├── vite.config.js
├── src/
│ ├── main.js ← entry point
│ ├── scss/
│ │ ├── main.scss ← master stylesheet
│ │ ├── _variables.scss ← Bootstrap variable overrides
│ │ ├── _custom.scss ← your custom component styles
│ │ └── _utilities.scss ← custom utility classes
│ ├── js/
│ │ └── app.js
│ └── assets/
│ ├── images/
│ └── fonts/
└── dist/ ← compiled output (gitignore this)
src/scss/main.scss — the import order is critical:
// 1. Override Bootstrap's defaults BEFORE importing
@import 'variables';
// 2. Bootstrap source
@import 'bootstrap/scss/bootstrap';
// 3. Your custom styles AFTER (can reference Bootstrap mixins/variables)
@import 'custom';
@import 'utilities';
src/scss/_variables.scss — your overrides:
// Colors
$primary: #fd4766;
$primary-rgb: 253, 71, 102;
$success: #10b981;
$danger: #ef4444;
// Typography
$font-family-sans-serif: 'Inter', system-ui, sans-serif;
$font-size-base: 0.9375rem;
$headings-font-weight: 700;
// Borders
$border-radius: 8px;
$border-radius-lg: 12px;
$border-color: #e5e7eb;
// Shadows
$box-shadow-sm: 0 1px 4px rgba(0,0,0,0.06);
$box-shadow: 0 4px 16px rgba(0,0,0,0.08);
src/main.js — entry point:
import './scss/main.scss'
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
// Your app code
import './js/app.js'
Angular + Bootstrap Project
Angular manages Bootstrap through angular.json:
my-angular-app/
├── angular.json
├── src/
│ ├── app/
│ │ ├── app.component.ts
│ │ └── app.component.html
│ └── styles/
│ ├── styles.scss ← global styles (configured in angular.json)
│ ├── _variables.scss ← Bootstrap overrides
│ └── _custom.scss ← component overrides
angular.json — add Bootstrap CSS and JS:
{
"projects": {
"my-app": {
"architect": {
"build": {
"options": {
"styles": ["src/styles/styles.scss"],
"scripts": ["node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"]
}
}
}
}
}
}
src/styles/styles.scss:
@import 'variables';
@import 'bootstrap/scss/bootstrap';
@import 'custom';
For component-specific styles in Angular, use each component's .scss file. Angular's ViewEncapsulation handles scoping automatically.
Multi-Page HTML Site
For sites with multiple pages sharing the same styles:
website/
├── index.html
├── about.html
├── blog/
│ ├── index.html
│ └── post-1.html
├── assets/
│ ├── css/
│ │ ├── bootstrap.min.css ← local copy (optional)
│ │ └── site.css ← custom styles
│ ├── js/
│ │ ├── bootstrap.bundle.min.js
│ │ └── site.js
│ └── images/
│ ├── logo.svg
│ └── favicon.ico
Using local copies of Bootstrap files (instead of CDN) makes the site work offline and avoids CDN dependency. Download from getbootstrap.com and commit to your repo.
What to Gitignore
# Build output
dist/
build/
# Dependencies (npm/yarn will reinstall)
node_modules/
# Environment files
.env
.env.local
# OS files
.DS_Store
Thumbs.db
Never commit node_modules/ — it's regenerated from package.json. Always commit package.json and package-lock.json.
Key Rules
Load order matters: Bootstrap CSS → your CSS → Bootstrap JS → your JS. Custom CSS after Bootstrap ensures your overrides win. JS at the end of body prevents render blocking.
Override in Sass, not CSS: When using Sass, override Bootstrap variables before the import. When using CDN, override with CSS custom properties after. Never edit Bootstrap's source files directly.
One styles entry point: Have a single main.scss that imports everything in order. This makes the cascade predictable.
Frequently Asked Questions
Need a Full Bootstrap 5 Admin Dashboard?
Get a complete Angular 21 + Bootstrap 5 dashboard with 50+ components — built by the same team behind BootstrapPlanet.
Browse Templates →Use code FIRST30 for 30% off your first purchase.