Create a blog with multiple authors, author pages, and bylines
9 min read1870 words
In this tutorial, you'll transform a single-author blog into a full multi-author publication with author profiles, individual author pages, and rich bylines.
Tip
Default Theme Has This Built-In!
Bengal's default theme includes complete multi-author support:
Author pages with social links and post listings
Author bylines in blog posts (enablecontent.authorfeature)
Author index page listing all contributors
If you're using the default theme, you may only need to add frontmatter — no template work required! This tutorial shows both how to use the built-in features and how to customize them.
Note
Who is this for?
This guide is for developers building team blogs, publication sites, or any content with multiple contributors. You should be familiar with Bengal basics from the Build a Blog tutorial.
Goal
By the end of this tutorial, you will have:
Structured author data in frontmatter
Rich author bylines with avatars and social links
Dedicated author profile pages
An author listing page
Posts filtered by author
Prerequisites
A Bengal site (runbengal new site my-blogif starting fresh)
Add structured author information to your blog posts.
Bengal supports two ways to specify authors in frontmatter:
Simple (name only):
---title:"Getting Started with Python"author:Jane Smith---
Structured (full profile):
---title:"Getting Started with Python"author:name:Jane Smithavatar:/images/authors/jane.jpgbio:Senior developer and tech writertwitter:janesmithgithub:janesmithlinkedin:janesmithwebsite:https://janesmith.dev---
Create a test post atcontent/blog/python-basics.md:
---title:"Python Basics for Beginners"date:2024-01-15draft:falseauthor:name:Jane Smithavatar:/images/authors/jane.jpgbio:Senior developer specializing in Python and web technologiestwitter:janesmithgithub:janesmithtags:["python","tutorial"]---# Python Basics for BeginnersLearn the fundamentals of Python programming...
Tip
Avoid Repetition
Instead of repeating full author data in every post, you can define authors in a data file and reference them. We'll cover this later.
Create a profile for Jane atcontent/authors/jane-smith.md:
---title:Jane Smithtype:authoravatar:/images/authors/jane.jpgbio:|Jane is a senior developer with 10 years of experience in Pythonand web technologies. She writes about best practices,tutorials,and the joy of clean code.location:San Francisco,CAtwitter:janesmithgithub:janesmithlinkedin:janesmithwebsite:https://janesmith.dev---## About JaneJane has been writing code since she was 12 years old. She's passionate
about developer experience and making complex topics accessible.
## Interests
- Python ecosystem
- Web performance
- Developer tools
- Teaching and mentoring
Create the author page template attemplates/authors/single.html:
{% extends "default/base.html" %}
{% block content %}
<articleclass="author-profile"><headerclass="author-header">
{% if page.metadata.avatar %}
<imgsrc="{{ page.metadata.avatar }}"alt="{{ page.title }}"class="author-profile-avatar">
{% end %}
<divclass="author-header-info"><h1>{{ page.title }}</h1>
{% if page.metadata.location %}
<pclass="author-location">📍 {{ page.metadata.location }}</p>
{% end %}
{% if page.metadata.bio %}
<pclass="author-bio-long">{{ page.metadata.bio }}</p>
{% end %}
<divclass="author-links">
{% if page.metadata.website %}
<ahref="{{ page.metadata.website }}">Website</a>
{% end %}
{% if page.metadata.twitter %}
<ahref="https://twitter.com/{{ page.metadata.twitter }}">Twitter</a>
{% end %}
{% if page.metadata.github %}
<ahref="https://github.com/{{ page.metadata.github }}">GitHub</a>
{% end %}
</div></div></header><divclass="author-content">
{{ page.content | safe }}
</div><sectionclass="author-posts"><h2>Posts by {{ page.title }}</h2>
{# Use author index for O(1) lookup (faster than where filter) #}
{% let author_posts_refs = site.indexes.author.get(page.title) | list %}
{% let author_posts = author_posts_refs | resolve_pages | sort_by('date', reverse=true) %}
{% if author_posts %}
<ulclass="post-list">
{% for post in author_posts %}
<li><ahref="{{ post.href }}">{{ post.title }}</a><time>{{ post.date | date('%B %d, %Y') }}</time></li>
{% end %}
</ul>
{% else %}
<p>No posts yet.</p>
{% end %}
</section></article>
{% end %}
Tip
Performance Tip: Use Author Index
Thesite.indexes.authorprovides O(1) lookup for author posts, which is much faster than filtering all pages withwhere('author.name', ...). The author index is automatically built during site generation and maps author names to their post references.
For even more advanced use cases, consider using theauthor_viewfilter (see the default theme implementation for examples).
For larger teams, define authors in a data file instead of repeating info in every post.
Createdata/authors.yaml:
jane-smith:name:Jane Smithavatar:/images/authors/jane.jpgbio:Senior developer specializing in Pythontwitter:janesmithgithub:janesmithjohn-doe:name:John Doeavatar:/images/authors/john.jpgbio:Frontend architect and design systems experttwitter:johndoegithub:johndoe
You'll need a custom template function to resolve this:
# In a build hook or custom extensiondefget_author(key):# site.data supports safe access - returns empty dict if missingreturnsite.data.authors[key]ifkeyinsite.data.authorselseNone
Note
This advanced pattern requires a build hook. See Build Hooks for details.
Summary
You now have a fully functional multi-author blog with: