A minimal Gulp 4 + Bootstrap 5.3 starter for static site development.
Blank means no theme, not no tooling.
You get a working build pipeline: SCSS compilation, reusable HTML partials, image optimization, minification and live reload. Bootstrap supplies the UI components; this repo supplies the development environment around them.
No theme. No prebuilt pages. No design system. No third-party UI plugins.
- Node.js 20 or newer, and npm
- Gulp 4.x — installed locally by
npm install, no global install needed
Gulp 5 is not supported yet. It changes default stream encoding and enforces stricter async task completion. The pipeline plugins (
gulp-imagemin,gulp-clean-css) have not been verified under Gulp 5. Do not upgrade the Gulp major version without testing the full build first.
git clone https://github.com/azwiki/gulp-bootstrap.git my-project
cd my-project
rm -rf .git
npm install
npm startThe browser opens automatically. Edit files in src/ — Gulp rebuilds and reloads on every change.
src/ → Gulp → dist/
↑ ↓
edit here website
Always edit files in
src/.dev/anddist/are generated on every build — never edit them by hand.
- Bootstrap 5.3, used as a prebuilt vendor package (copied from
node_modules, not compiled from source) - Gulp 4 build pipeline
- SCSS compilation with Autoprefixer
- HTML includes / partials (
gulp-file-include) - JavaScript copying
- Image optimization (GIF, PNG, SVG; other formats are copied as-is)
- CSS minification (
clean-css) in production builds - BrowserSync live reload
- Separate development and production builds
- Favicon and web manifest support
- No custom theme or visual design
Three equivalent ways — all produce the same project layout.
Same as Quick Start. rm -rf .git disconnects the project from this repository; run git init afterwards to start your own history.
- On the GitHub page click Code → Download ZIP
- Unzip and open a terminal in the folder
- Run:
npm install
npm startnpm install is required first: it fetches Gulp, Bootstrap, Sass and the other tools listed in package.json. Use npm run build:dist instead of npm start if you only want a one-off build.
mkdir my-project && cd my-project
npm install gulp-bootstrapA postinstall script then:
- copies
gulpfile.js,src/,README.mdand.gitignoreinto your project root (existing files are skipped, never overwritten); - merges the
scriptsanddevDependenciesfrom this package into yourpackage.json; - removes the
gulp-bootstrapentry from yourdependencies.
Finish the setup:
rm -rf node_modules package-lock.json
npm install
npm startThe cleanup discards the temporary install (node_modules holds only the gulp-bootstrap package at that point, and the lockfile still references it). The second npm install fetches the real build tools: gulp, bootstrap, sass, and the rest.
npm install # once, after cloning or changing package.json
npm start # build:dist, then serve dist/ with BrowserSync live reload (Ctrl+C to stop)
npm run build:dev # → dev/, uncompressed, for debugging (not served, not watched)
npm run build:dist # → dist/, minified, ready to deploydist/ is the finished static site — upload its contents to any static web server.
The watcher rebuilds pages, partials, SCSS, main.js, images (including the favicon) and root files. It does not watch gulpfile.js or the vendor copy tasks (Bootstrap, and any library you add) — restart npm start after changing those.
gulp-bootstrap/
├── gulpfile.js # build logic
├── package.json
├── LICENSE
├── .gitignore
├── scripts/
│ └── postinstall.js # used by the npm install method only
├── src/ # you work here — everything else is generated
│ ├── index.html # pages: any .html file, in src/ or its subfolders
│ ├── robots.txt
│ ├── site.webmanifest
│ ├── partials/ # reusable pieces (not built as pages)
│ │ ├── _head.html
│ │ ├── _navbar.html
│ │ ├── _footer.html
│ │ └── _scripts.html
│ └── assets/
│ ├── scss/main.scss # your styles — empty by default
│ ├── js/main.js # your JavaScript
│ └── img/
│ ├── favicon/ # favicon.png (linked from _head.html) + 192/256/512 px PNGs for site.webmanifest — replace with your own
│ └── screenshot.webp
├── dev/ # generated by build:dev (git-ignored)
└── dist/ # generated by build:dist / npm start (git-ignored)
clean:dev / clean:dist wipe the output directory before every build.
Create src/about.html (any name, .html, not inside partials/):
<!doctype html>
<html lang="en">
<head>
@@include('_head.html', {
"title": "About",
"description": "About our website",
"keywords": "about, bootstrap"
})
</head>
<body>
@@include('_navbar.html', { "siteName": "gulp-bootstrap" })
<main class="container py-5">
<h1>About</h1>
<p>Your page content goes here.</p>
</main>
@@include('_footer.html', { "siteName": "gulp-bootstrap" })
@@include('_scripts.html')
</body>
</html>Gulp processes the includes and writes dist/about.html. Add the link to src/partials/_navbar.html.
Pages can also live in subfolders (src/blog/post.html → dist/blog/post.html). Use @@webRoot for every asset and page link so paths stay correct at any depth (see below).
Repeated HTML lives in src/partials/. Change _navbar.html once and every page picks it up on the next build.
Values passed from a page are available in the partial as @@param:
<title>@@title</title>
<meta name="description" content="@@description">
<meta name="keywords" content="@@keywords">@@webRoot is built into gulp-file-include: the relative path from the current page to the site root (. for index.html, .. for a page one folder deep). The bundled partials use it for all links:
<link rel="stylesheet" href="@@webRoot/assets/css/main.css">
gulp-file-includelimitation: only flat@@paraminterpolation is reliable inside@@include(...).@@if/@@elsecan render as literal text. Keep partials free of conditional logic.
| What | Where | Notes |
|---|---|---|
| Your styles | src/assets/scss/main.scss |
Compiled to assets/css/main.css, loaded after bootstrap.min.css, so same-specificity rules override Bootstrap |
| Your JavaScript | src/assets/js/main.js |
Copied as-is; kept separate from vendor code |
| Images | src/assets/img/ |
GIF, PNG and SVG are optimized during the build; JPEG and WebP are copied unchanged |
| Favicon | src/assets/img/favicon/favicon.png |
Replace with your own PNG; linked from _head.html and processed like any other image |
Bootstrap itself is never modified:
Bootstrap → vendor framework (node_modules)
main.scss → your styles
main.js → your JavaScript
Because Bootstrap's Sass is not compiled, Sass variables (
$primary, etc.) cannot be customized. Override styles inmain.scssor via--bs-*CSS variables.
npm install <package>Then make the library's files part of the build. Two options:
- Ready-made
.min.js/.min.css: reference them directly from a partial (or a CDN) — no Gulp changes needed. - Files from
node_modules: add a copy task togulpfile.js, as in the example below.
1. Install
npm install glightbox2. Add paths and copy tasks to gulpfile.js
Mirror the existing bootstrapjs:dev / bootstrapjs:dist tasks.
In the path object, add one entry to each of dev, dist and src:
dev: { /* ... */ glightbox: 'dev/assets/vendor/glightbox/' },
dist: { /* ... */ glightbox: 'dist/assets/vendor/glightbox/' },
src: { /* ... */ glightbox: [
'node_modules/glightbox/dist/css/glightbox.min.css',
'node_modules/glightbox/dist/js/glightbox.min.js'
] },Add the tasks next to the Bootstrap ones:
/* GLightbox — copied as-is from node_modules */
gulp.task('glightbox:dev', function () {
return gulp.src(path.src.glightbox).pipe(gulp.dest(path.dev.glightbox));
});
gulp.task('glightbox:dist', function () {
return gulp.src(path.src.glightbox).pipe(gulp.dest(path.dist.glightbox));
});Add them to the gulp.parallel(...) list of build:dev and build:dist:
gulp.parallel('html:dev', /* ... */ 'root:dev', 'glightbox:dev')
gulp.parallel('html:dist', /* ... */ 'root:dist', 'glightbox:dist')Restart npm start — Gulp does not reload its own config.
3. Load the files in partials
src/partials/_head.html — after bootstrap.min.css:
<link rel="stylesheet" href="@@webRoot/assets/vendor/glightbox/glightbox.min.css">src/partials/_scripts.html — before main.js:
<script src="@@webRoot/assets/vendor/glightbox/glightbox.min.js"></script>4. Initialize in src/assets/js/main.js
// init lightbox for all links with class "glightbox"
GLightbox({ selector: '.glightbox' });5. Use it in a page
<a href="@@webRoot/assets/img/photo.jpg" class="glightbox" data-gallery="gallery1">
<img src="@@webRoot/assets/img/photo-thumb.jpg" alt="Photo" class="img-fluid">
</a>Check that the files appear under dist/assets/vendor/glightbox/.
The starter intentionally ships no extra frontend libraries. Add only what your project needs.
npm outdated # current / wanted (within package.json ranges) / latest
npm update # update everything within the ranges in package.json
npm update bootstrap # update only Bootstrap (stays within ^5.3.3)
npm install bootstrap@latest # jump to a new major version — read the release notes first
npm install bootstrap@5.3.3 # pin an exact version
npm update glightbox # update a vendor library you addedAfter any update, run npm run build:dist and check the site in the browser.
Do not run
npm install <package>@latestforgulp,del,gulp-imageminorimagemin-pngquant. They are pinned with~on purpose.gulp@latestis Gulp 5, which is not supported; newer majors ofdel,gulp-imageminandimagemin-pngquantare ESM-only and cannot be loaded by therequire()calls ingulpfile.js. Plainnpm updatekeeps them within their safe ranges.
Most frontend templates start with a full visual design and a pile of plugins, so a new site begins with deleting things. gulp-bootstrap goes the other way:
Bootstrap
+ build pipeline
+ HTML partials
+ empty project styles
+ empty project JavaScript
Then add only what the website actually requires.
MIT — see LICENSE.
