ssg  
Where to Discuss?

Local Group

Preface

Goal: Using static data feature.

Source Code

This article use tutor-07 theme. We will create it step by step.


8: Friends

As every SSG does, eleventy also has feature to access static data.

Data: friends.json

I always like to give a link to my fellow blogger folks. So I made a special data for these great people.

[
   {
      "title": "Nanda 'Yunee' Okitavera",
      "url": "https://okitavera.me/"
   },
   {
      "title": "BanditHijo (R)-Chive",
      "url": "http://bandithijo.com/"
   },
   {
      "title": "Elianiva",
      "url": "https://elianiva.github.io/"
   },
   {
      "title": "Sira Argia (Aflasio)",
      "url": "https://aflasio.netlify.app/"
   },
   ...
]

Filter: Shuffle

I need to show five bloggers randomly for each pages. We already have limit filter in previous article. Now we require to add a new shuffle filter in main configuration. Since nunjucks does not have a built in function for shuffle. We need to add shuffle filter in .eleventy.js:

  // Random Filter: With the help from google search engine
  eleventyConfig.addNunjucksFilter("shuffle", function(array) {
    return helper.shuffle(array);
  });
  
  // Limit Filter: Copy paste from Jérôme Coupé
  eleventyConfig.addNunjucksFilter("limit", function(array, limit) {
    return array.slice(0, limit);
  });

After duckduckwent fo a while, I got this shuffle code from stackoverflow:

Where the code in helper.js file is as below:

 
exports.shuffle = function(array) {

  var currentIndex = array.length;
  var temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {
    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
};

Later you can use this filter as code below:

  {% set links = friends | shuffle | limit(5) %}

Again, you can see how flexible nunjucks is.

Partial Widget: Nunjucks Friends

{% extends "layouts/widget.njk" %}

{% set color = 'pink' %}

{% block widget_header %}
  <strong>Isle of Friends</strong>
  <span class="fas fa-child is-pulled-right"></span>
{% endblock %}

{% block widget_body %}
  {% set links = friends | shuffle | limit(5) %}

  <ul class="widget-list">
    {%- for friend in links -%}
    <li><a href="{{ friend.url }}"
      >{{ friend.title }}</a></li>
    {%- endfor -%}
  </ul>
{% endblock %}

Render: Browser

You can open page kind, or post kind, to test this widget.

11ty: Widget: Friends


I have four blogs, each already have generated archive data. So it makes sense that I put backlinks from my own static blog, in each post.

Data: archive-github.json

My generated data from my Jekyll site looks like below:

{
    "system-2020-02-02-presentation-linux-diversity-html": {
      "title": "Presentation - Learning Linux Diversity",
      "url": "/system/2020/02/02/presentation-linux-diversity.html"
    },
    "desktop-2020-01-20-presentation-desktop-customization-html": {
      "title": "Presentation - Desktop Customization",
      "url": "/desktop/2020/01/20/presentation-desktop-customization.html"
    },
    "desktop-2019-12-03-awesome-presentation-statusbar-html": {
      "title": "Awesome WM - Presentation - Statusbar",
      "url": "/desktop/2019/12/03/awesome-presentation-statusbar.html"
    },
    ...
}

I put this in my eleventy static data directory manually.

Data: archive-gitlab.json

And, my generated data from my Hugo site looks like below:

{  
    "/frontend/2020/05/15/template-koa/": {
      "title": "Template - Koa",
      "content": "Templating Engine Configuration in KoaJS.",
      "url": "/frontend/2020/05/15/template-koa/",
      "author": "epsi",
      "category": "frontend"
    },
    "/frontend/2020/05/13/template-express-handlebars/": {
      "title": "Template - Express - Handlebars",
      "content": "Feeding Data in ExpressJS, and Process in a Loop with Handlebars.",
      "url": "/frontend/2020/05/13/template-express-handlebars/",
      "author": "epsi",
      "category": "frontend"
    },
    ...
}

I also put this in my eleventy static data directory manually.

Filter: Value

I do not want to make different archive for each target sites. My Jekyll data archive should be the same for all reader. And my Hugo data archive also should be the same for all reader.

For this to be happened, I need to add new value filter in main configuration. Since nunjucks does not have a built in function for value. We need to add value filter in .eleventy.js:

  // values Filter: With the help of w3schools
  eleventyConfig.addNunjucksFilter("values", function(array) {
    return Object.values(array);
  });

Later you can use this filter as code below:

  {% set archives = archives_github | values %}

Partial Widget: Nunjucks Archive Github

{% extends "layouts/widget.njk" %}

{% set color = 'orange' %}

{% block widget_header %}
  <strong>Linux/BSD Desktop Customization</strong>
  <span class="fas fa-fingerprint is-pulled-right"></span>
{% endblock %}

{% block widget_body %}
  {% set archives = archives_github | values %}
  {% set posts = archives | shuffle | limit(5) %}

  <ul class="widget-list">
    {%- for post in posts -%}
    <li><a href="http://epsi-rns.github.io{{ post.url }}"
      >{{ post.title }}</a></li>
    {%- endfor -%}
  </ul>
{% endblock %}

Render: Browser

You can open page kind, or post kind, to test this widget.

11ty: Widget: Backlinks from Github

Partial Widget: Nunjucks Archive Gitlab

{% extends "layouts/widget.njk" %}

{% set color = 'pink' %}

{% block widget_header %}
  <strong>Web/Mobile Development</strong>
  <span class="fas fa-fingerprint is-pulled-right"></span>
{% endblock %}

{% block widget_body %}
  {% set archives = archives_gitlab | values %}
  {% set posts = archives | shuffle | limit(5) %}

  <ul class="widget-list">
    {%- for post in posts -%}
    <li><a href="http://epsi-rns.gitlab.io{{ post.url }}"
      >{{ post.title }}</a></li>
    {%- endfor -%}
  </ul>
{% endblock %}

Render: Browser

You can open page kind, or post kind, to test this widget.

11ty: Widget: Backlinks from Gitlab


We have already seen in previous article, that we can generate our own custom data:

Data: archives.json

Using previously saved file _data/archives.json. Note that this archive saved manually from generated content.

{
  
    "15032535": {
      "title": "Deftones - Be Quiet and Drive",
      "url":   "/lyrics/deftones-be-quiet-and-drive/"
    },
  
    "18091335": {
      "title": "Disturbed - Stupify",
      "url":   "/lyrics/disturbed-stupify/"
    },
  
    "15071535": {
      "title": "Marilyn Manson - Sweet Dreams",
      "url":   "/lyrics/eurythmics-sweet-dreams/"
    },
  
    "18011535": {
      "title": "House of Pain - Jump Around",
      "url":   "/lyrics/house-of-pain-jump-around/"
    },
  
    "15072535": {
      "title": "Marilyn Manson - Redeemer",
      "url":   "/lyrics/marylin-manson-redeemer/"
    },
  ...
}

The ID, comes from dates and minutes. automatic generated by script from previous article.

Page Content: Frontmatter

Now we can add variable in page content. Consider name the variable related_link_ids. This should contain array of id in yaml.

---
layout    : post
title     : Marilyn Manson - Redeemer
date      : 2015-07-25 07:35:05
tags      : ["industrial metal", "90s"]

related_link_ids :
  - 15071535  # Sweet Dreams
---
...
---
layout    : post
title     : Marilyn Manson - Sweet Dreams
date      : 2015-07-15 07:35:05
tags      : ["industrial metal", "90s"]

related_link_ids :
  - 15072535  # Redeemer
---
...

11ty: Widget: Related Links ID

Filter: Value

Unlike previous widget that need values filter. This widget require keys filter.

  // values Filter: MDN web docs
  eleventyConfig.addNunjucksFilter("keys", function(array) {
    return Object.keys(array);
  });

Later you can use this filter as code below:

  {% set ids = archives | keys %}

Layout: Nunjucks Page or Post

Consider examine only related-posts. The widget should only be shown, if ids set in frontmatter.

  <aside class="column is-one-thirds">
    {%- if related_link_ids -%}
      {% include "widget/related-posts.njk" %}
    {%- endif -%}
  </aside>

Notice that, the widget won’t be shown, if there is no ids set in frontmatter.

{% extends "layouts/widget.njk" %}

{% set color = 'lime' %}

{% block widget_header %}
  <strong>Related Posts</strong>
  <span class="fa fa-link is-pulled-right"></span>
{% endblock %}

{% block widget_body %}
  <ul class="widget-list">
  {%- for link_id in related_link_ids -%}
    <li>
      {% set ids = archives | keys %}
      {%- for id in ids -%}

        {%- if link_id == id -%}
        <a href="{{ archives[id].url | url }}"
          >{{ archives[id].title }}</a>
        {%- endif -%}

      {%- endfor -%}
    </li>
  {{ end }}
  {%- endfor -%}
  </ul>
{% endblock %}

I know it is a little bit complex. And lately, I rarely use this related_link_ids feature myself. But I still keep this feature for a few of my posts.

Render: Browser

You can open post kind, to test this widget.

11ty: Widget: Related Posts


11: Summary

Layout: Post

As a summary here is the post layout.

{% extends "layouts/columns-double.njk" %}

{% block main_color %}{{ color or 'blue' }}{% endblock %}

{% block blog_header %}
  {% include "post/blog-header.njk" %}
{% endblock %}

{% block aside %}
  <aside class="column is-one-thirds">
    {%- if related_link_ids -%}
      {% include "widget/related-posts.njk" %}
    {%- endif -%}

    {% include "widget/archive-grouped.njk" %}
    {% include "widget/tags.njk" %}
  </aside>
{% endblock %}

{% block aside_widget_all %}
  <aside class="column is-one-thirds">
    {% include "widget/tags.njk" %}
    {% include "widget/archive-grouped.njk" %}
    {% include "widget/recent-posts.njk" %}
    
    {%- if related_link_ids -%}
      {% include "widget/related-posts.njk" %}
    {%- endif -%}

    {% include "widget/friends.njk" %}
    {% include "widget/archive-gitlab.njk" %}
    {% include "widget/archive-github.njk" %}
    
    {% include "widget/oto-spies.njk" %}
    {% include "widget/affiliates.njk" %}
  </aside>
{% endblock %}

You can add or remove widget, as you want them to be.

Render: Browser

The looks in desktop screen is shown as below figure:

11ty: Widgets in Desktop


What is Next ?

Consider continue reading [ Eleventy - Pagination - Intro ]. We are going to move on to complex component called pagination.

Thank you for reading.