gnrt - static site generator
2020-06-13
Although there are already plenty of static site generators available, it is quite hard to find one which is fast, lightweight, minimalist, easy to use and which simply generates HTML files from structured content, using templates.
Enter gnrt
, a static site generator written in Python 3.
Using gnrt
By default, gnrt
does not need any configuration.
You write Markdown content files in the content
folder, execute gnrt
, and it will output HTML files in the public
folder.
$ cat content/index.md The body content here. $ gnrt Generated 0 includes Generated 1 targets $ cat public/index.html <p>The body content here.</p>
Let's add some structure by creating a Jinja2 template in the templates
folder and pointing to it in the content frontmatter.
$ cat templates/page.j2 <html> <body> {{ body }} </body> </html>
$ cat content/index.md --- template: page.j2 --- The body content here.
$ gnrt Generated 0 includes Generated 1 targets $ cat public/index.html <html> <body> <p>The body content here.</p> </body> </html>
Since it is not very convenient to point to the same template each time you create new content, let's create a configuration file and add some defaults.
$ cat config.yml defaults: template: page.j2
We can then remove the template key from the frontmatter, and re-generate.
$ gnrt Generated 0 includes Generated 1 targets
$ cat public/index.html <html> <body> <p>The body content here.</p> </body> </html>
Lists
Menus can be generated using the concept of lists.
$ cat config.yml defaults: template: page.j2 lists: menu: template: nav.j2
$ cat templates/nav.j2 <ul> {% for key, value in items %} <li><a href="{{ value.link }}">{{ value.title }}</a></li> {% endfor %} </ul>
Let's say that we created an About page (content/about.md), and re-generate.
$ gnrt Generated 1 includes Generated 2 targets
The menu has been generated as includes/menu.html
.
$ cat includes/menu.html <ul> <li><a href="/about.html">about</a></li> <li><a href="/index.html">index</a></li> </ul>
This menu can then be included in the generated output, by adding {{ menu }} somewhere in the page template, and by pointing to it either in the frontmatter, or easier, in the configuration file.
$ cat config.yml defaults: template: page.j2 menu: includes/menu.html lists: menu: template: nav.j2
$ cat templates/page.j2 <html> <body> {{ menu }} {{ body }} </body> </html>
Lists can be filtered (e.g. by category of content), sorted (e.g. by publication date) and limited to a certain number of items.
Example:
nav-latest-articles: template: nav-article.j2 filter: key: category value: article sort: published reverse: true limit: 2
The target
key allows to specify where the generated list will be saved; this makes it possible to generate a RSS feed for instance:
rss: filter: key: category value: article sort: published reverse: true template: rss.j2 target: public/rss.xml
Data access
The whole website dataset and configuration is available in the templates and markdown content through the {{ data }} and {{ config }} keys.
$ cat content/index.md --- id: home title: Home link: / --- Welcome to the homepage. Check the [about]({{ data.about.link }}) page or read the [articles]({{ data.articles.link }}) !
Fast and lightweight
gnrt 0.1.1 contains around 100 lines of Python code and is feature complete, at least for my needs - I use it to generate this website.
On a decent computer, it generates 1000 files (containing random text) in less than 1 second.
$ find content/ -type f | wc -l 1000 $ find content/ -type d | wc -l 51 $ time gnrt Generated 0 includes Generated 1000 targets real 0m0,612s user 0m0,574s sys 0m0,032s
Open source
gnrt is available on GitHub under the MIT license and can be installed via:
pip install gnrt
There is an example website implementation in the repository.
Last updated: 2022-03-20