Preface
Step Zero: Prepare modular HTML using Nunjucks template
A template system can help you produce healty code. Instead of long HTML, you can separate chunks of HTML element, into different files. You can find your element easily this way. So you can focus on specific HTML element.
Now I can put recurring long parts such as navbar, in separate file, and focus on small parts, such as widget, or blog post layout. Using one big HTML only without template used to be exhausting, but now it is easier with modular files.
This is basically a template introduction. It looks like learning frontend, using backend approach. Of course you need some adaptation to use template approach. Learning process may take while, but it is worth to learn.
1: Ready to Use Examples.
Bootstrap examples provided in with this article series. I intentionally make result of compiled templates for each chapter. You can just open HTML file in the browser, and see the result. This way is easier for beginner.
Repository
You can start the journey by clone the git repository.
❯ git clone https://gitlab.com/epsi-rns/tutor-html-bootstrap5/
You can see all chapters here, form Step-00 to Step-10.
Open HTML using File Manager
There is two ways to open this file.
- Using file protocol
- Using http protocol
You just can open the ready to use HTML file for each chapter, by right-clicking the file in file manager and open the HTML file, in your favorite browser, such as chrome, edge, or firefox.
This compiled HTML files are available for all chapters.
Open HTML using Browser Sync
For convenience, you can also open HTML file using HTTP protocol. This can be done using using a few options, such as javascript based browser-sync.
❯ browser-sync start --server --directory
Alternatively you can use Python.
❯ python -m http.server
Or even PHP
❯ php -S localhost:8000
Since we want to also use Nunjucks template later on, we’d better use browser-sync for easy integration with Nunjucks.
❯ npm i -g browser-sync
❯ cd ~/bs5/tutor-html-bootstrap5
❯ browser-sync start --server --directory
[Browsersync] Access URLs:
--------------------------------------
Local: http://localhost:3000
External: http://192.168.0.191:3000
--------------------------------------
UI: http://localhost:3001
UI External: http://localhost:3001
--------------------------------------
[Browsersync] Serving files from: ./
Now you can open localhost:3000 in your browser. You can change also change the port number if you need. The browser can navigate into all chapters.
Then you can open the file that you need.
You can check the URL in below section of that Qutebrowser, is different than previous file protocol.
2: Modularization
I use different approach, while developing each case. Instead of just giving raw HTML files, I modularized each HTML parts into chuncks.
Gulp, Grunt, Webpack?
The thing is I don’t want to repeat myself. This could be done using Nunjucks and Grunt.
Since I have already make an article about Nunjucks and Grunt. I think I’d better use other method. After some research, I found this good article below:
I decide to use Gulp instead of Grunt.
Directory Structure
Modular approach is easier for beginner. For each steps, we have this directory structure.
❯ tree
.
├── 001-html-layout.njk
├── contents
│ └── main.njk
├── heads
│ └── meta.njk
├── layouts
│ └── base.njk
└── shared
├── footer.njk
└── header.njk
You can see all the separated templates here.
Using Nunjucks
We need to install Nunjucks first.
❯ npm i -g nunjucks nunjucks-cli
We can operate the Nunjucks in CLI.
❯ cd ~/bs5/tutor-html-bootstrap5
❯ cd step-00/views
❯ nunjucks 001-html-layout.njk -p . -o .
Rendering: 001-html-layout.njk
~/bs/tutor-html-bootstrap5/step-00/views
Now check the directory, we can see a new HTML file has generated there
❯ exa
001-html-layout.html contents layouts
001-html-layout.njk heads shared
We are going to automate this later, in this article.
3: Partials Nunjucks
For better explanation, consider examine the HTML source, as partial templates.
Source Code: Step-00
Source code for this chapter can be obtained here:
Simple Layout
You can begin learning HTML document, without any framework. Our simple HTML5 layout could be like this.
<!DOCTYPE html>
<html>
<head>
{% include './heads/meta.njk' %}
</head>
<body>
{% include './shared/header.njk' %}
{% include './contents/main.njk' %}
{% include './shared/footer.njk' %}
</body>
</html>
Base Layout
For flexibility reason we can split code above using inhertance.
Base file:
<!DOCTYPE html>
<html>
<head>
{% block htmlhead %}
{% endblock %}
</head>
<body>
{% block header %}
{% endblock %}
{% block content %}
{% endblock %}
{% block footer %}
{% endblock %}
</body>
</html>
Paired with blocks:
{% extends './layouts/base.njk' %}
{% block htmlhead %}
{% include './heads/meta.njk' %}
{% endblock %}
{% block header %}
{% include './shared/header.njk' %}
{% endblock %}
{% block content %}
{% include './contents/main.njk' %}
{% endblock %}
{% block footer %}
{% include './shared/footer.njk' %}
{% endblock %}
Mostly I start from page layout, then HTML elements later.
Meta and Main
And the rest, Meta and Main.
<title>Your mission. Good Luck!</title>
<!-- main -->
<div>
<p>To have, to hold, to love,
cherish, honor, and protect?</p>
<p>To shield from terrors known and unknown?
To lie, to deceive?</p>
<p>To live a double life,
to fail to prevent her abduction,
erase her identity,
force her into hiding,
take away all she has known.</p>
</div>
Header and Footer
Also Header and Footer.
<!-- header -->
<p><i>Your mission, should you decide to accept it.</i></p>
<br/>
<!-- footer -->
<br/>
<p><i>As always, should you be caught or killed,
any knowledge of your actions will be disavowed.</i></p>
HTML Output
Static Page
The compiled output is long,
This would be shown as below figure:
Now we can open it in browsersync or using file directly.
4: Automation
Disclaimer: For new bootstrap user, you can skip this part entirely.
Typing command to compile Nunjucks is cumbersome.
We can utilize Gulp
and automate each chapter.
We need to configure Gulp to do these task:
- Generate HTML: One chapter at a time
- Generate All HTML
- Watch Changes
Gulp Configuration
The configuration can be obtained here:
Installation
You can refer to:
With exception I add ‘merge-stream’ package.
Prepare Gulpfile
First we need to initialize required variables:
const gulp = require("gulp")
const nunjucksRender = require("gulp-nunjucks-render")
const browserSync = require("browser-sync").create();
const merge = require('merge-stream');
And also defined all chapters, that need to be automated.
const folders = [
'step-00',
'step-01',
'step-02',
'step-03',
'step-04',
'step-05',
'step-06',
'step-07',
'step-08',
'step-09',
'step-10'
];
One chapter at a time
Generate HTMLs
folders.map( (task) => {
const folder = './'+task;
gulp.task(task, () => {
return gulp.src(folder+'/views/*.njk')
.pipe(nunjucksRender({
path: [folder+'/views'],
}))
.pipe(gulp.dest(folder+'/'))
});
});
Then you can run in CLI
❯ gulp step-00
[22:23:18] Using gulpfile ~/bs5/tutor-html-bootstrap5/gulpfile.js
[22:23:18] Starting 'step-00'...
[22:23:18] Finished 'step-00' after 50 ms
All chapters at once
Generate HTMLs
gulp.task("all-html", () => {
const tasks = folders.map( (folder) => {
return gulp.src(folder+'/views/*.njk')
.pipe(nunjucksRender({
path: [folder+'/views']
}))
.pipe(gulp.dest(folder+'/'))
});
return merge(tasks);
});
In CLI, you can type.
❯ gulp all-html
[22:23:41] Using gulpfile ~/bs5/tutor-html-bootstrap5/gulpfile.js
[22:23:41] Starting 'all-html'...
[22:23:42] Finished 'all-html' after 522 ms
Watching Task
Regenerate for any changes.
gulp.task("watch", () => {
browserSync.init({
server: {
baseDir: "./"
},
directory: true
})
gulp.watch('./**/*.html')
.on("change", browserSync.reload);
folders.map( (task) => {
folder = './' + task
gulp.watch(folder+'/views/**/*.njk',
gulp.series(task));
});
});
In CLI, you can type.
❯ gulp watch
[22:24:04] Using gulpfile ~/bs5/tutor-html-bootstrap5/gulpfile.js
[22:24:04] Starting 'watch'...
[Browsersync] Access URLs:
--------------------------------------
Local: http://localhost:3000
External: http://192.168.0.191:3000
--------------------------------------
UI: http://localhost:3001
UI External: http://localhost:3001
--------------------------------------
[Browsersync] Serving files from: ./
Consideration
Is Gulp overkill?
Making this configuration is considered easy for me. And once it runs, I can automate all chapters, So I can sit on my chair, and get my brain focused on HTML code. But I know gulp is not for everyone. So it is your choice to decide.
Again, for new bootstrap user, you can skip this part entirely. You don’t need Gulp to learn bootstrap. But you’d better go back later, when you have time, to learn javascript.
What is Next 🤔?
After prepartion, we can use bootstrap right away.
Consider continue reading [ Bootstrap 5 - Minimal ].