Templates

Like Hyde, kurama uses a simple separation of content from layouts, or, in this case, templates.

However, unlike Hyde, all templates are expected to be HTML files.

At minimum, you are expected to create one template called page.html.

This template is used to render all pages, except for posts and archives, which are generated from entry.html and archive.html respectively.

To keep things simple and uniform, you should also create some kind of base template that the three aforementioned templates all inherit from, which does not have a required name.

Your base template will look like this:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>
            {% block title %}
            {% endblock title %}
        </title>
        <link rel="stylesheet" href="/css/common.css">
        <link rel="stylesheet" href="/css/style.css">
        <link rel="stylesheet" href="/css/dark.css">
        {% block feeds %}
        {% endblock feeds %}
    </head>
    <body>
        <header id="banner">
            <h1>{{ site.name }}</h1>
            <p>{{ site.tagline }}</p>
        </header>
        <nav id="mainNav">
            <ul id="menu">
                {% for section in site.sections %}
                <li onclick="return true">
                    <span class="bold">{{ section.name }}</span> <span class="arrow">˅</span>
                    <ul class="zone">
                        {% for link in section.links %}
                        {% if link.url == current_dir %}
                        <li id="current">{{ link.name }}</li>
                        {% elif link.url == output_file %}
                        <li id="current">{{ link.name }}</li>
                        {% elif 'mailto:' in link.url %}
                        <li><a href="{{ link.url }}">{{ link.name }}</a></li>
                        {% else %}
                        <li><a href="/{{ link.url }}">{{ link.name }}</a></li>
                        {% endif %}
                        {% endfor %}
                    </ul>
                </li>
                {% endfor %}
            </ul>
        </nav>
        <main>
            {% block content %}
            {% endblock content %}
        </main>
    </body>
    <footer id="siteFooter">
        <p>Copyright © 2026 {{ site.author }}.</p>
    </footer>
</html>

In the example above, the site configuration used sections for specifying the navigation, so loops could handle everything, while making sure the contact link is rendered properly.

Child Templates

After creating the base template, you can then create another template like this:

{% extends "base.html" %}
{% block title %}
{% if page.metadata.title %}
{{ page.metadata.title }} = {{ site.name }}
{% else %}
{{ site.name }}
{% endif %}
{% endblock title %}
{% block feeds %}
<link rel="alternate" type="application/feed+json" href="{{ feed_url }}" title="JSON Feed">
{% endblock feeds %}
{% block content %}
{{ content }}
{% endblock content %}

This calls in the template base.html and modifies it appropriately, with the blocks created back in the base.

Entry

If this were for a post, you could do something like this instead:

{% extends "base.html" %}
{% block title %}
{% if page.metadata.title %}
{{ page.metadata.title }} - {{ site.name }}
{% else %}
{{ site.name }}
{% endif %}
{% endblock title %}
{% block feeds %}
<link rel="alternate" type="application/feed+json" href="{{ feed_url }}" title="JSON Feed">
{% endblock feeds %}
{% block content %}
<article>
    <header>
        <h2>{{ page.metadata.title | title }}</h2>
        <p>{{ page.metadata.date | date(format="%B %d, %Y") }}</p>
    </header>
    {{ content }}
</article>
{% endblock content %}

This will format the post's publication date as full month name DD, YYYY.

This functionality was present out of the box in Tera version 1, but was separated out into a seperate library in version 2, which is what Kurama uses.

However, kurama does include that separate crate as a dependency so this is still present in kurama.

Tags are also accessed through the metadata property of this variable, but you must use the built in slugify filter, which is used like how the date is formatted, to help you build a link to the tag.

This would be done like this:

{% for tag in page.metadata.tags %}
<a href="/tags/{{ tag.name | slugify }}">{{ tag.name }}</a>
{% endfor %}

The above will assumes that the site is a blog, so it will target the tags directory of the site's root.

Unlike most slugifying functions, including the one Bryce could have imported from one of kurama's dependencies, this function will use underscores to split things up.

Archive

An archive template would look like this:

{% extends "base.html" %}
{% block title %}
{% if site.blog_name %}
{% if archive.page > 1 %}
{{ site.blog_name }} ({{ archive.page }}) - {{ site.name }}
{% else %}
{{ site.blog_name }} - {{ site.name }}
{% endif %}
{% else %}
{% if archive.page > 1 %}
{{ site.name }} ({{ archive.page }})
{% else %}
{{ site.name }}
{% endif %}
{% endif %}
{% endblock title %}
{% block feeds %}
<link rel="alternate" type="application/feed+json" href="{{ feed_url }}" title="JSON Feed">
{% endblock feeds %}
{% block content %}
<h2>{{ site.blog_name }}</h2>
{% for post in posts %}
{% set date_path = (post.metadata.date | date(format="%Y/%m/%d/"))%}
<div class="post">
    <h2><a href="/{{ site.blog_path }}/posts/{{ date_path }}{{  post.metadata.slug }}.html">{{ post.metadata.title }}</a></h2>
    <p>{{ post.metadata.date | date(format="%B %d, %Y")}}</p>
</div>
{% endfor %}
{% if pages > 1 %}
<nav id="pageNav">
    {% if prev_page %}
    <p><a href="{{ prev_page }}"><</a></p>
    {% endif %}
    <p>Page {{ archive.page }} of {{ pages }}</p>
    {% if next_page %}
    <p><a href="{{ next_page }}">></a></p>
    {% endif%}
</nav>
{% endif %}
{% endblock content %}

This will automatically display the page number in the archive as part of the title, as well as other necessary information.

Variables

When creating templates, you might want to access certain information.

To grab these details, here are the variables you should know about.

Shared

site

The data present in the site configuration.

Use this to grab the site name, tagline, navigation info, and author.

feed_url

The URL of the feed.

The feed URL will always match a context, like the main feed, a tag feed, or a feed for the page in an archive.

Most of the time, it will be the main feed.

Pages & Posts

page

This gives access to details concerning posts and pages.

To grab the metadata, you would use the metadata property, as seen above.

Since posts are the only ones expected to have dates, the date property of metadata is not available for pages.

content

The content of the page or post in HTML format.

output_file

The file that the page or posts is to be saved to.

Like archive's current_dir, this can be used to highlight the current page of the navigation, but will not take pagination into account, since only archives can have pages.

Archives

archive

This is like page from above, but only for archives.

Use this to access the name of the archive, though one will not exist unless it is a tag archive, and the page number.

current_dir

This will give the directory for the archive, which can be used to keep the archive's link highlighted as a visitor traverses the pages contained.

posts

The posts for the current page of the archive.

pages

The total number of pages in the archive.

prev_page

The previous page in the archive.

next_page

The next page in the archive.