Preparing for a real hullabaloo
Sep 24, 2018 · 6 min
This last one’s about building out the pages for the blog, so that I can use the home page for something else.
In this edition, we’re gonna be adding a page for this blog to call home. Then we’ll build out the template for articles and add some navigation.
Before we get started, create a new branch and open another beer.
$ git checkout -b blog
Dependencies
First we need to add a library to our project to handle pagination. We’ll get into it later in this article, but we need to add one to produce redirects as well.
Edit the Gemfile
then add jekyll-paginate
and jekyll-redirect-from
to the :jekyll_plugins
block.
group :jekyll_plugins do
...
gem "jekyll-paginate"
gem "jekyll-redirect-from"
end
Next you’ll need to make some additions to _config.yml
. First add jekyll-paginate
and jekyll-redirect-from
to the plugins:
block.
plugins:
...
- jekyll-paginate
- jekyll-redirect-from
For contextual purposes, we want to keep everything in the address bar that’s blog related behind /blog/
. To do that, add directives for pagination, and permalink.
...
paginate: 4
paginate_path: /blog/:num/
permalink: /blog/:categories/:title
As you may have been able to deduce, we’ll end up with paginated pages at /blog/2/
and articles at /blog/category/article-title
With dependencies in place we can get started on our next tasks.
Blog Pages
In the spirit of displaying our collection of articles in a reasonable manner, the blog’s home page will be…
- located at
/blog/
- paginated
- with the newest article displayed first
- 4 articles per page
- each article displayed within 1 column of a 2x2 square
- bonus! a featured article at the top of page 1
Sounds pretty straight forward, so let’s get started.
On the subject of listing articles, we’re going to build an article preview that can be included throughout the site. It’ll accept two arguments. A post
object containing the post to preview, and a boolean called box
to indicate whether or not you’d like the preview to include the box class.
_includes/article-preview.html
<article{% unless include.box == false %} class="box"{% endunless%}>
<h3 class="title"><a href="{{ include.post.url | relative_url }}">{{ include.post.title | escape }}</a></h3>
{% assign topic = post.categories.first %}
<p class="subtitle">{% if topic %}in {{ topic }} {% endif %}{{ include.post.date | date: "%b %-d, %Y" }}</p>
<div class="content">
{{ include.post.excerpt }}
</div>
<a href="{{ include.post.url }}" class="button is-primary is-outlined">Keep reading</a>
</article>
With that out of the way, let’s start working on our blog page. Create a /blog/
directory, and add an index.html
file.
$ mkdir src/blog
src/blog/index.html
---
layout: page
---
{% if paginator.page == 1 %}
<section class="hero is-primary">
<div class="hero-body">
<div class="container">
<h1 class="title">
Featured
</h1>
{% assign featured = site.posts.last %}
{% include article-preview.html post=featured %}
</div>
</div>
</section>
{% endif %}
<section class="section section-blog-page">
<div class="container">
<h2 class="title">{% if paginator.page == 1 %}Latest{% else %}Page {{ paginator.page }}{% endif %}</h2>
<div class="columns is-multiline">
{%- for post in paginator.posts -%}
<div class="column is-half">
{% include article-preview.html post=post box=false %}
</div>
{%- endfor -%}
</div>
</div>
</section>
At this point we can implement pagination with the help of Bulma’s pagination component.
_includes/nav-pagination.html
{% if paginator.total_pages > 1 %}
<nav class="pagination is-right" role="navigation" aria-label="pagination">
<a {% if paginator.previous_page %}href="{{ paginator.previous_page_path }}"{% endif %} class="pagination-previous"{% unless paginator.previous_page %} disabled{% endunless %}>Previous</a>
<a {% if paginator.next_page %}href="{{ paginator.next_page_path }}"{% endif %} class="pagination-next"{% unless paginator.next_page %} disabled{% endunless %}>Next</a>
<ul class="pagination-list">
{% for page in (1..paginator.total_pages)%}
{% capture page-url %}{% if page == 1 %}{{ site.paginate_path | replace: ':num/', '' }}{% else %}{{ site.paginate_path | replace: ':num', page }}{% endif %}{% endcapture %}
<li><a href="{{ page-url | prepend: site.baseurl | prepend: site.url }}" class="pagination-link{% if page == paginator.page %} is-current{% endif %}">{{ page }}</a></li>
{% endfor %}
</ul>
</nav>
{% endif %}
To wrap things up for the blog page, we’ll add nav-pagination.html
under the articles in /src/blog/index.html
.
<hr>
{% include nav-pagination.html %}
Articles
Display header
- Title of article as H1
- Display article tags above Title
- Display date beneath Title
- Show article contents under Title
<section class="section section-blog-post">
<article class="container">
<header class="header has-text-centered">
<div class="tags is-centered">
{% for tag in page.tags %}
<span class="tag">{{ tag | capitalize }}</span>
{% endfor %}
</div>
<h1 class="title">{{ page.title }}</h1>
<p class="subtitle">{{ page.date | date: "%b %d, %Y" }}</p>
</header>
<div class="content">
{{ content }}
</div>
</article>
</section>
Getting around
After our visitor has finished reading, you must be able to feed that voracious appetite with moar delicious content. We’ll need…
- Links to the previous and next articles under the article
- The next 5 most recent articles to the right of the article
- Redirect category pages
Ok, so let’s begin with the previous and next links. Jekyll is nice enough to provide us with page.previous
and page.next
. We’ll just need to be careful to check if we’re on the first or last post. In those instances we’ll just say “current page” and display the title as text.
/src/_includes/prev-next.html
<div class="columns is-mobile">
<div class="column is-6">
{% if page.previous %}
<h2>Previous article</h2>
<p><a href="{{ page.previous.url | prepend: site.baseurl | prepend: site.url }}" title="{{ page.previous.title }}" rel="prev">« {{page.previous.title}}</a></p>
{% else %}
<h2>Current article</h2>
{{page.title}}
{% endif %}
</div>
<div class="column is-6 has-text-right">
{% if page.next %}
<h2>Next article</h2>
<a href="{{ page.next.url | prepend: site.baseurl | prepend: site.url }}" title="{{ page.next.title }}" rel="next">{{page.next.title}} »</a>
{% else %}
<h2>Current article</h2>
{{page.title}}
{% endif %}
</div>
</div>
After saving, include it in src/_layouts/post.html
under the article.
{% include prev-next.html %}
For our last edit to src/_layouts/post.html
we’ll do a quick unordered list to show off the latest articles. Skip the current article.
<ul>
{% for article in site.posts limit: 5 %}
{% if article.title == page.title %}{% continue %}{% endif %}
<li><a href="{{ article.url }}">{{ article.title }}</a></li>
{% endfor %}
</ul>
Finally, if you’ll recall how we setup article urls, each article is behind a category page (ex: /blog/category/article-title). If a lookie-loo were to visit /blog/category/
they would be treated to a generic index page (or perhaps a 404). Building out category pages is certainly on our todo list, but it’s out of scope for this round. Instead, we’re going to use that jekyll-redirect-from
plugin to redirect requests over to /blog/
Open /src/blog/index.html
and update it’s frontmatter.
...
redirect_from:
- /blog/site-update/
For now, we only have one category to redirect. As you add articles with new categories, be sure to come back and update this block. On that note, if you want to create category pages at a later date, you’ll need to delete the relevant lines.
Final thoughts
At last! We can wrap things up with a quick push to our remote repo for a PR.
$ git add .
$ git commit -m "Upgrading blog"
$ git push origin blog
At this stage, we’re free to do what we need to do with the home page because we have an awesome new blog page. Not only that but we took the opportunity to give our articles a rudimentary sense of direction.
Previous article
Next article
Topics
- updates