Templating Guide


Norgolith uses the Tera templating engine to generate HTML from your Norg content. This guide will walk you through creating, customizing, and extending templates for your Norgolith site.

Template Basics

Templates in Norgolith are written in HTML with Tera’s templating syntax. They are stored in the templates/ directory of your site or theme.

Default Templates

Example: Basic Template

<!-- templates/post.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>{{ metadata.title }}</title>
  </head>
  <body>
    <h1>{{ metadata.title }}</h1>
    <div class="content">{{ content }}</div>
  </body>
</html>

Template Variables

Norgolith provides several variables for use in your templates:

Important
  • Right now posts will retrieve all of the content files from posts/ directory in content/, including draft posts. You will have to filter it on your own in the templates by checking for the draft metadata field.
  • Additionally to the regular metadata from the posts, posts will also contain a raw metadata field, containing the HTML code for the post. This is useful if you are creating a recent posts section and you want to display part of the post content additional to the post description. See the picture below for an example.
demo recent posts with post description

Example

<!-- templates/post.html -->
<h1>{{ metadata.title }}</h1>
<div class="content">{{ content }}</div>

Template Inheritance

Use template inheritance to avoid duplicating code. For example:

<!-- templates/base.html -->
<html>
  <head>
    <title>{{ site.title }}</title>
  </head>
  <body>
  {% block content %}{% endblock %}
  </body>
</html>

<!-- templates/post.html -->
{% extends "base.html" %}

{% block content %}
<h1>{{ metadata.title }}</h1>
<div class="content">{{ content }}</div>
{% endblock %}

Filters and Functions

Tera comes with some built-in global filters and functions which you can use directly in your templates. Additionally, Norgolith also exposes custom Tera functions for use in templates:

<!-- You can also use it without providing an argument -->
<footer>
  <span>Copyright &copy; {{ now(format="%Y") }}</span>
</footer>
<!-- Usage example -->
{% if metadata.toc %}
  <div>
    {% set toc_html = generate_toc(toc=metadata.toc, list_type="ol") %}
    <h3>
      Table of Contents
    </h3>
    <nav>
      {{ toc_html | safe }}
    </nav>
  </div>
{% endif %}

Advanced Templating Techniques

Loops and Conditionals

Tera supports loops and conditionals for dynamic content.

Example: Looping Over Categories

<ul>
  {% for category in metadata.categories %}
    <li>{{ category }}</li>
  {% endfor %}
</ul>

Example: Conditional Rendering

{% if metadata.draft %}
  <div class="draft-notice">This post is a draft.</div>
{% endif %}

Including Partial Templates

You can include other templates within a template.

Example: Including a Header

{% include "header.html" %}

Practical Examples

Example 1: Blog Post Template

<!-- templates/post.html -->
{% extends "base.html" %}

{% block content %}
<article>
  <h1>{{ metadata.title }}</h1>
  <p class="meta">By {{ metadata.authors | join(sep=", ") }} on {{ metadata.created | date(format="%Y-%m-%d") }}</p>
  <div class="content">{{ content }}</div>
  <ul class="categories">
  {% for category in metadata.categories %}
    <li>{{ category }}</li>
  {% endfor %}
  </ul>
</article>
{% endblock %}

Example 2: Homepage Template

<!-- templates/index.html -->
{% extends "base.html" %}

{% block content %}
<section class="posts">
  {% for post in posts %}
    <article>
      <h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
      <p class="meta">By {{ post.authors | join(sep=", ") }} on {{ post.created | date(format="%Y-%m-%d") }}</p>
      <span class="description">{{ post.description }}</span>
    </article>
  {% endfor %}
</section>
{% endblock %}

Troubleshooting Template Issues

Common Issues and Fixes

Template Not Rendering

Missing Variables

Inheritance Errors

Best Practices

Organizing Templates