In this tutorial, I will instruct you about how to create a page to show all of an author’s posts, without using any plugins.

This post was inspired by the Jasper2 theme, which is a port of Ghost’s Casper theme. In that theme, the author pages are generated by a plugin, which can be inconvenient.

This guide will walk you through how to setup an equivalent system without using a plugin.

Setup

This guide takes advantage of Jekyll’s Collections feature, and the fact that every item in a collection can be made to output a page.

Config

Open your _config.yml and add the following:

collections:
  authors:
    output: true
    permalink: author/:title/

defaults:
  -
    scope:
      path: ""
      type: authors
    values:
      layout: author


The first block (collections) defines authors as a new collection. It says that the files should be output (meaning that all files in the _authors/ directory map to pages on your site), and that the url for those pages should be your.website.url/author/title-of-your-file/

The second block (defaults) says that all posts with the type authors (ie, anything in the authors collection) should use the author layout.

Author Files

Now, let’s create a file in our collection that tells Jekyll about one of our authors.

Create the _authors directory, and create a new file in that directory username.md, where username is the name that will be used in the url. I want my url to be /author/jetroid/, so I’m going to create jetroid.md.

Now, the specifics of what you want to put in this file will vary depending on what you want to display on your author’s pages. Here’s the setup that I’m using, which includes real names, location, personal sites URL, a short bio, a path to a picture, and social media usernames. Don’t feel restricted by what to include here; use whatever your site needs!

---
username: jetroid
name: Jet A. Holt
location: Earth 🌏
url_full: https://jetholt.com/
url_short: jetholt.com
bio: I'm Jet, a CS graduate who enjoys working on his own projects. I'm known for my Eurorack synth modules.
picture: assets/images/jet.jpg
facebook: Jetroid
twitter: jetroidmakes
instagram: jetroidmakes
---

You’ll need to create a file like this for every author on your site. Remember to create new files when adding new authors!

Specify Author Of Posts

This bit is simple!

Simply add authors: jetroid to the front matter of your post. Be sure to replace jetroid with the username of your author. If you have more than one author, you can create an array like this:

authors: [jetroid, jekyll, hyde]

Once done, your front matter might look something like this:

---
layout: post
title: Jekyll Author Pages
date: 2020-05-10 22:41:40 +0100
authors: jetroid
---

TIP: You can add the following to your _config.yml’s defaults section to have your posts default to a specific author. (You can still use a different author in individual posts using the authors front matter variable.)

  -
    scope:
      path: ""
      type: post
    values:
      author: jetroid

Be sure to replace jetroid with the username of your author!

Edit Templates

By now, we’re set up, and Jekyll knows information about our authors, and who authored which posts.

We need to display that information in the HTML of our site!

Post Written By

Let’s start by editing the template used for our posts. On my site, posts use the post.html layout (in the _layouts/ directory), so I’ll be editing that.

Everyone’s post.html layout will be different, so I can only provide some code here.

Modify these snippets and include them wherever you want to link to the author of a post. This will probably be in post.html layout, and perhaps even somewhere in your index.html to.

NB: You may have to change post to page to get these snippets to work!

Simple Snippet

This first simple snippet simply writes each author’s names (as hyperlinks to their author pages) to new lines, similar to the below:

Jet A. Holt

Dr. Jekyll

Mr. Hyde

This simpler example is easier for you to modify to add your own customisations, like a personal image for each author.

{% for author in site.authors %}
	{% if post.authors contains author.username or author.username == post.authors %}
	    <a href="{{ site.url }}{{ site.baseurl }}/author/{{ author.username }}">{{ author.name }}</a>
	{% endif %}
{% endfor %}

It simply iterates through every author that jekyll knows about, and if they were one of the authors of our post, creates a new link to them.

Complex Snippet

This more complex snippet writes Written by Jet A Holt, Dr. Jekyll, and Mr. Hyde, where each name is a hyperlink to that author’s page.

{% assign authordata = '' | split:'@' %}
{% for author in site.authors %}
    {% if post.authors contains author.username or author.username == post.authors %}
        {% capture data %}
        	<a href="{{ site.url }}{{ site.baseurl }}/author/{{ author.username }}">{{ author.name }}</a>
        {% endcapture %}
        {% assign authordata = authordata | push: data %}
    {% endif %}
{% endfor %}
<p>Written by {{ authordata | array_to_sentence_string }}</p>

It does much the same as the first snippet, but creates an array and pushes our data into it. In this case, the data is our author’s name and the hyperlink. At the end, we print the contents of the array as a ‘sentence string’, which adds punctuation (and the word ‘and’) to it as necessary.

Author Template

Next, we want to create the template for our author pages. This will be the template that is rendered when we go to the /author/jetroid/ URL.

Again, this will vary drastically from site to site, so I will just be including some useful snippets.

Note that all of the fields you created in your _authors/username.md file are accessible here using the page variable. For example, jetroid’s page.name is Jet A. Holt.

Header, Photo, Bio

We’ll start with something easy, simply pasting their photo, name, and bio to the page:

{% if page.picture %}
    <img class="author-profile-image" src="/{{ page.picture }}" alt="{{ page.name }}" />
{% endif %}
<h1 class="site-title">{{ page.name }}</h1>
{% if page.bio %}
    <h2 class="author-bio">{{ page.bio }}</h2>
{% endif %}
{% if page.location %}
    <div class="author-location">{{ page.location }}</div>
{% endif %}

We might want to create a list of all of their posts.

This snippet filters all the posts to just include the ones written by the author, and includes a link to the post.

{% for post in site.posts %}
	{% if post.authors contains page.username or page.username == post.authors %}
		<a href="{{ site.url }}{{ site.baseurl }}{{ post.url }}">{{ post.title }}</a>
	{% endif %}
{% endfor %}

NB: I tried to do a more elegant solution using where_exp, but ran into a weird bug. Sad.

How Many Posts They Wrote

In your header for this author, you might want to include some data about how many posts they have contributed to the site. This can be seen below. It writes ‘No posts’ if they haven’t posted.

{% assign number_of_posts = 0 %}
{% for post in site.posts %}
    {% if post.authors contains page.username or page.username == post.authors %}
        {% assign number_of_posts = number_of_posts | plus: 1 %}
    {% endif %}
{% endfor %}
{% if number_of_posts == 0 %}No posts{% elsif number_of_posts == 1 %}1 post{% else %}{{ number_of_posts }} posts{% endif %}
{% if page.url_short and page.url_full %}
<a href="{{ page.url_full }}" target="_blank" rel="noopener">{{ page.url_short }}</a>
{% endif %}
{% if page.twitter %}
    <a href="https://twitter.com/{{ page.twitter }}" target="_blank" rel="noopener">
    	<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"/></svg>
    </a>
{% endif %}
{% if page.facebook %}
    <a href="https://facebook.com/{{ page.facebook }}" target="_blank" rel="noopener">
    	<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M19 6h5V0h-5c-3.86 0-7 3.14-7 7v3H8v6h4v16h6V16h5l1-6h-6V7c0-.542.458-1 1-1z"/></svg>
    </a>
{% endif %}
{% if page.instagram %}
    <a href="https://instagram.com/{{ page.instagram }}" target="_blank" rel="noopener">
    	<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
    </a>
{% endif %}

The following CSS might help:

svg {
	height: 1.8rem;
	color: white;
}
svg path {
	stroke: white;
}

P.S. I'm late to the party, but I recently got a twitter account that you can follow here.