Mindbrews Podcast coming in Soon! Stay Tuned!

Developers & Open Source

Superpower your Static HTML with Static Jinja!

Ever had the need to create repetitive static pages in Plain Old HTML and not one of the fancy new JS Frameworks such as VueJs or ReactJs? Creating pages that are of the same design but differ in content.

What is StaticJinja?

StaticJinja is a library for easily deploying static sites using the Jinja2 template engine.” that is what it says in the official documentation, but what it actually does is combine all your partial templates and render them into top-level static HTML files what you would have written otherwise.

Take a simple example, you have 3 pages on your website: Home, About, Contact. Each page has 3 basic things: Header (menu), Footer, and the Body. Now traditionally what you’ll do is create header and footer in any one page and then copy the same code in rest 2 pages. So, you’ll have something like this:

Without StaticJinja

With StaticJinja however, you’ll create a base template (_base.html) with 2 partial components, _header.html, and _footer.html and extend this base template to create the 3 pages, so you’ll get exact same output but the benefit is that if you change anything in the menu, you just need to edit the _header.html file and just re-build the website and it’ll be updated on all your pages.

With added superpowers of Staticjinja

Let’s get started,

Let’s create a basic Hello World Webpage using staticjinja and see it in action.

Installing Staticjinja

Create a virtual environment and install staticjinja in it:

# Create a Virtual Environment
> virtualenv -p python3 venv
# Activate the Virtual Environment
# Bash (Linux/Mac)
> source venv/bin/activate
# Fish Shell
> source venv/bin/activate.fish
# Windows
> ./venv/Source/activate
# Install Staticjinja
(venv) > pip install staticjinja

Creating templates

The templates folder

Staticjinja picks up templates from the templates folder, this can be configured but for now, let’s stick with defaults and create this folder.

> mkdir templates

Staticjinja is based on Jinja2 Templating Engine, Jinja2 is an extremely powerful templating engine if you’re a Django user you’ll find it similar to DTL (Django Templating Language) which is more or less similar to Jinja2. You can read more about the template syntax at https://jinja.palletsprojects.com/en/2.11.x/templates/

Create a base template

A base template all the common code that’ll be duplicated along with all the pages. Create a file _base.html in the templates folder and place the following code in it:

<!DOCTYPE html>
<html>
  <head>
    <title>[% block title %}{% endblock } | Hello World</title>
    <!-- Bootstrap v4 CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
    {% block extra_css %}{% endblock %}
    {% block header_js %}{% endblock %}
  </head>
  <body>
     <div class="container">
        {% block body %}{% endblock %}
     </div>
     <!-- Bootstrap JS -->
     <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
     <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
     {% block footer_js %}{% endblock %}
  </body>
</html>

What the heck is that? Let’s go step by step:

Anything written in {% %} are referred to as tags and each tag has a special meaning, you can refer to Jinja2 documentation for more tags.

{% block block_name %}{% endblock %}: The block tag is used to create blocks in a template, blocks are overridable parts of the template that any child template can override. You’ll understand its use later in the article. I’ve created 5 blocks in the template:

  • title: This block will be used to set the page title
  • extra_css: This block will be used to include any page-specific stylesheet or style tags in the page.
  • header_js: Similar to extra_css block, this tag will be used to include any page-specific javascript in the head.
  • body: This block will be used to add individual content of each page
  • footer_js: Similar to header_js block, this tag will be used to include any page-specific javascript in the footer.

Rest of the code is self-explanatory since the article assumes you have a basic knowledge of Web Development.

2. Adding Header and Footer

Let’s add a basic menu and a basic footer to our website, our code will become something like this:

<!DOCTYPE html>
<html>
  <head>
    <title>[% block title %}{% endblock } | Hello World</title>
<!-- Bootstrap v4 CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
{% block extra_css %}{% endblock %}
    {% block header_js %}{% endblock %}
</head>
  <body>
     <header>
       <ul class="list-inline">
          <li class="list-inline-item">
             <a href="index.html">Home</a>
          </li>
          <li class="list-inline-item">
             <a href="about.html">About</a>
          </li>
          <li class="list-inline-item">
             <a href="contact.html">Contact</a>
          </li>
       </ul>
     </header>
     <div class="container">
         {% block body %}{% endblock %}
     </div>
     <footer>
         This is a footer with some content.
     </footer>
      <!-- Bootstrap JS -->
     <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
     <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
{% block footer_js %}{% endblock %}
</body>
</html>

Now, let’s do it the “StaticJinja” way, create a new folder partials with two files in it, _header.html and _footer.html. Your new folder structure will look like this:

root
-> templates
   -> partials
      -> _header.html
      -> _footer.html
   -> _base.html
-> venv

Now let’s move our header and footer to these files, your files will look like:

<!-- _header.html -->
<header>
   <ul class="list-inline">
      <li class="list-inline-item">
          <a href="index.html">Home</a>
      </li>
      <li class="list-inline-item">
          <a href="about.html">About</a>
      </li>
      <li class="list-inline-item">
          <a href="contact.html">Contact</a>
      </li>
   </ul>
</header>

and _footer.html will look like:

<!-- _footer.html -->
<footer>
  This is a footer with some content.
</footer>

and now we’ll use {% include %} tag to include these templates in the base template and remove the header and footer from there.

<!DOCTYPE html>
<html>
  <head>
    <title>[% block title %}{% endblock } | Hello World</title>
<!-- Bootstrap v4 CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
{% block extra_css %}{% endblock %}
    {% block header_js %}{% endblock %}
</head>
  <body>
     {% include 'partials/_header.html' %}
     <div class="container">
         {% block body %}{% endblock %}
     </div>
     {% include 'partials/_footer.html' %}
     <!-- Bootstrap JS -->
     <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
     <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
{% block footer_js %}{% endblock %}
</body>
</html>

Now that our base template is ready, let’s extend it and create our pages.

3. Extending the base template

Create a new file index.html in the templates folder, and add the following to it:

{% extends '_base.html' %}
{% block title %}Home{% endblock %}
{% block body %}
<div class="row">
  <div class="col-12 text-center">
    <h1>Hello World</h1>
    <p>This is the home page.</p>
  </div>
</div>
{% endblock %}

You might be seeing some friendly tags here, say hi to block tag! Let’s understand the code step by step:

  • {% extends %}: This is another of the Jinja template tag and is used to extend base the templates. It should always be the first tag in the template if you’re going to extend it. To extend, just add the tag and pass the relative path to the base template you want to inherit from.
  • {% block title %}: Remember defining this tag in _base.html? Once we extended the base template we can now override various blogs and add the overridden content which will be added during the build.
  • {% block body %}: This is same as overriding the title block, content added here will be added to body block during the build.

Similarly, create the about.html and contact.html files

{% extends '_base.html' %}
{% block title %}About{% endblock %}
{% block body %}
<div class="row">
  <div class="col-12 text-center">
    <h1>Hello World</h1>
    <p>This is the about page.</p>
  </div>
</div>
{% endblock %}

contact.html

{% extends '_base.html' %}
{% block title %}Contact{% endblock %}
{% block body %}
<div class="row">
  <div class="col-12 text-center">
    <h1>Hello World</h1>
    <p>This is the contact page.</p>
  </div>
</div>
{% endblock %}

Now we’ve all the files ready and we’re ready to do the first-ever build of StaticJinja, your current directory structure will look something like this:

root
-> templates
   -> partials
      -> _header.html
      -> _footer.html
   -> _base.html
   -> about.html
   -> contact.html
   -> index.html
-> venv

Building the site

Now that you’ve your environment and templates ready, you can simply build the site by executing the following command,

(venv) root> staticjinja build

This will recursively search for templates in the templates folder in . (i.e. current folder) whose names don’t start with a _ or . and will create the rendered files in . i.e. current folder. So, after running the command your directory structure will be something like this (notice the 3 new files in the root directory):

root
-> about.html
-> contact.html
-> index.html
-> templates
   -> partials
      -> _header.html
      -> _footer.html
   -> _base.html
   -> about.html
   -> contact.html
   -> index.html
-> venv

Open the index.html file in the root directory and check its contents, voila! It’ll look something like this:

<!DOCTYPE html>
<html>
  <head>
    <title>Home | Hello World</title>
<!-- Bootstrap v4 CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
</head>
  <body>
     <header>
       <ul class="list-inline">
          <li class="list-inline-item">
             <a href="index.html">Home</a>
          </li>
          <li class="list-inline-item">
             <a href="about.html">About</a>
          </li>
          <li class="list-inline-item">
             <a href="contact.html">Contact</a>
          </li>
       </ul>
     </header>
     <div class="container">
         <div class="row">
           <div class="col-12 text-center">
             <h1>Hello World</h1>
             <p>This is the home page.</p>
           </div>
         </div>
     </div>
     <footer>
         This is a footer with some content.
     </footer>
<!-- Bootstrap JS -->
     <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
     <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>
</html>

Awesome right? If you’ll open the remaining 2 files, you’ll see the completely rendered webpages.

But why?

This is just a basic use of StaticJinja. It can be used to build a static blog, static e-commerce pages, or static websites from dynamic data sources!

A lot more customization can be done via custom build script that uses StaticJinja to create “dynamically static” (Name suggestions for these types of websites are open) websites. Some of the use cases where I’ve personally used StaticJinja are:

  • Creating a multi-lingual website: I created a custom build script that reads a YML file and passes variables to the build context and builds all the files in different languages in different directories!
  • Creating a modular website with JSON data source: I created the website for our open source community, ALiAS, using StaticJinja which reads data for various sections from JSON files and passes them to build content to generate a static website. All the code is divided into modules and partial files that make collaboration easier, modules independent and removes data inconsistency!
  • Creating Product/Service Pages: While building static websites for service-based agencies, you come across the need where the layout is basically the same, all that differs is the content, like service name, service description, key points, images, etc. Staticjinja makes building these sites a breeze, you create a custom script and voila, any new service can be added or removed with just a command!

There are a lot more use cases where you can use StaticJinja, one of my friends used StaticJinja to create her blog using StaticJinja + Pelican!

That’s all for now, I’ll post more subsequent tutorials about creating custom scripts for StaticJinja which adds even more flexibility and power to this awesome library!

Let me know what you think, or if you’ve any queries/suggestions in the comments below, adios!

Author

Related posts
GlobalLatestPoliticsTechnology

India, Japan enters cyber-security deal on 5G

GlobalLatestNewsTechnologyWomen

Nobel in Chemistry: Pioneers in Gene Editing shatter history

ReviewsSpecificationsTechnology

MEET PETOI BITTLE: A PALM-SIZED CUTE ROBOT DOG

GlobalLatestSpecificationsTechnology

Apple Watch Series 6: Here’s Everything You Need To Know

Worth reading...
Deno: The Replacement for Node.js ?