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

For a simple HTML project: separate css/, js/ and images/ folders with an index.html at root. For a Sass/Vite project: src/ folder with scss/, js/ and assets/ subfolders. The compiled output goes to dist/. For Angular: Bootstrap is configured in angular.json, styles go in src/styles.scss.
Always after Bootstrap. In a plain HTML project, link your custom CSS file after Bootstrap's CDN link. In a Sass project, import Bootstrap first then your overrides: @import 'bootstrap/scss/bootstrap'; followed by your custom styles.
Create a custom.scss file. Before the Bootstrap import, define your variable overrides: $primary: #fd4766; $border-radius: 8px;. Then import Bootstrap: @import 'bootstrap/scss/bootstrap'. Your variables take precedence because Sass uses !default.

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.

Related Components