how to create a zola site
a walkthrough for building a static site with zola on sublimated. zola is a fast static site generator that uses markdown content and tera templates.
live demo: docs.sublimated.com/zola/
folder structure
minimum zola site:
mysite/
config.toml site configuration (required)
content/
_index.md homepage
templates/
base.html shared layout
index.html homepage template
page.html single page template
section.html section listing template1. config.toml
the only required field is base_url. sublimated uses this to detect zola sites.
base_url = "https://myspace.sublimated.com/mysite"
title = "my site"
description = "a zola site on sublimated"
compile_sass = false
build_search_index = false
generate_feeds = false
[extra]rules for base_url:
custom domain:
https://mysite.comsubdomain:
https://myspace.sublimated.com/mysitemust match the URL where the site will be served
2. content
content files are markdown with TOML frontmatter (between +++ markers).
+++
title = "my first post"
date = 2026-04-20
description = "hello world"
[taxonomies]
tags = ["demo", "first"]
+++
the post body goes here. standard markdown: **bold**, *italic*, [links](https://example.com), `code`.content organization
content/_index.md— homepage (or section root)content/blog/_index.md— creates a/blog/section with its own listingcontent/blog/my-post.md— a page at/blog/my-post/content/about.md— standalone page at/about/
sections vs pages
a folder with
_index.mdis a section — it lists its child pagesa standalone
.mdfile is a pagesections use
section.htmltemplate, pages usepage.html
co-located assets (images)
put images next to your markdown by using a folder with index.md:
content/blog/my-post/
index.md the post content
photo.jpg referenced as 
diagram.pngsublimated stores binary files in CAS and rewrites URLs to serve them from CDN. no special config needed.
frontmatter fields
+++
title = "page title" # required
date = 2026-04-20 # for sorting
description = "page description" # meta description
draft = false # hide from listings
weight = 1 # manual sort order
[taxonomies]
tags = ["tag1", "tag2"] # tag pages auto-generated
[extra]
author = "name" # custom fields, access via page.extra.author
image = "photo.jpg" # custom fields for templates
+++summary separator
use <!-- more --> to split a post into summary and body:
this part shows in listings as the summary.
<!-- more -->
this part only shows on the full page.access in templates: {{ page.summary }} and {{ page.content }}.
3. templates
templates use tera syntax with inheritance.
base.html — shared layout
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{% block title %}{{ config.title }}{% endblock %}</title>
<style>
/* all CSS goes here — inline for best performance */
body { font-family: -apple-system, sans-serif; max-width: 700px; margin: 0 auto; padding: 1rem; }
a { color: #1a5cc8; }
</style>
</head>
<body>
<header><a href="/">{{ config.title }}</a></header>
<main>{% block content %}{% endblock %}</main>
<footer>powered by zola + sublimated</footer>
</body>
</html>index.html — homepage
{% extends "base.html" %}
{% block content %}
{{ section.content | safe }}
{% set posts = get_section(path="blog/_index.md") %}
{% for page in posts.pages %}
<article>
<a href="{{ page.permalink }}">{{ page.title }}</a>
<time>{{ page.date | date(format="%B %d, %Y") }}</time>
</article>
{% endfor %}
{% endblock %}page.html — single page
{% extends "base.html" %}
{% block title %}{{ page.title }} | {{ config.title }}{% endblock %}
{% block content %}
<h1>{{ page.title }}</h1>
<time>{{ page.date | date(format="%B %d, %Y") }}</time>
<span>{{ page.reading_time }} min read</span>
{{ page.content | safe }}
{% endblock %}section.html — section listing
{% extends "base.html" %}
{% block content %}
<h1>{{ section.title }}</h1>
{{ section.content | safe }}
{% for page in section.pages %}
<article>
<a href="{{ page.permalink }}">{{ page.title }}</a>
<time>{{ page.date | date(format="%B %d, %Y") }}</time>
</article>
{% endfor %}
{% endblock %}useful template variables
config.title,config.description,config.base_urlpage.title,page.date,page.content,page.permalinkpage.reading_time,page.word_count,page.tocpage.taxonomies.tags— array of tag namespage.extra.*— custom frontmatter fieldspage.summary— content before<!-- more -->section.pages— child pages of a sectioncurrent_path— current URL path (useful for nav active states)
4. shortcodes
shortcodes are reusable snippets. create tera templates in templates/shortcodes/.
templates/shortcodes/note.html:
<div style="background:#dbeafe;border-left:3px solid #3b82f6;padding:0.75rem 1rem;margin:1rem 0;border-radius:4px">
<strong>Note:</strong> {{ body }}
</div>use in markdown:
{%/* note() */%}
this is an important note.
{%/* end */%}5. taxonomies (tags)
enable in config.toml:
taxonomies = [{ name = "tags" }]create templates:
templates/tags/list.html— all tags pagetemplates/tags/single.html— posts for one tag
add tags in frontmatter:
[taxonomies]
tags = ["cooking", "travel"]zola auto-generates /tags/ and /tags/cooking/ pages.
6. push and build
via git:
git add .
git commit -m "my zola site"
git pushor via CloudStorage — just save files, they sync automatically.
sublimated detects config.toml with base_url, sends text files to the zola WASM builder, stores the output, and serves it at your URL. builds typically take under 1 second.
7. image resizing
append query params to image URLs for on-demand resizing:
<img src="{{ page.extra.image }}?w=128">?w=128— resize to 128px wide (keeps aspect ratio)works on any image served through sublimated CDN
8. search
zola can generate a client-side search index using elasticlunr.js.
enable in config.toml:
build_search_index = truethis produces two files in the build output:
elasticlunr.min.js— the search librarysearch_index.en.js— the index data (setswindow.searchIndex)
create a search page:
content/search.md:
+++
title = "search"
template = "search.html"
+++templates/search.html:
{% extends "base.html" %}
{% block content %}
<h1>search</h1>
<input type="text" id="search-input" placeholder="type to search..." autofocus />
<p id="search-meta"></p>
<ul id="search-results"></ul>
<script src="{{ config.base_url }}elasticlunr.min.js"></script>
<script src="{{ config.base_url }}search_index.en.js"></script>
<script>
(function () {
var index = elasticlunr.Index.load(window.searchIndex);
var input = document.getElementById("search-input");
var results = document.getElementById("search-results");
var meta = document.getElementById("search-meta");
input.addEventListener("input", function () {
var query = input.value.trim();
results.innerHTML = "";
if (!query) { meta.textContent = ""; return; }
var hits = index.search(query, { expand: true });
meta.textContent = hits.length + " result" + (hits.length !== 1 ? "s" : "");
for (var i = 0; i < hits.length; i++) {
var doc = index.documentStore.getDoc(hits[i].ref);
var li = document.createElement("li");
var body = (doc.body || "").substring(0, 200);
li.innerHTML = '<a href="' + doc.id + '">' + (doc.title || doc.id) + '</a>'
+ '<p>' + body + (body.length >= 200 ? '...' : '') + '</p>';
results.appendChild(li);
}
});
})();
</script>
{% endblock %}live example: docs.sublimated.com/zola/search/
what works
markdown with TOML frontmatter
tera templates with inheritance
syntax highlighting (40+ themes, 200+ languages)
shortcodes (body and inline)
taxonomies (tags, categories)
table of contents (auto-generated from headings)
internal links (
@/path/to/file.md— validated at build time)reading time and word count
Atom/RSS feeds
clean URLs
dark mode (CSS
prefers-color-scheme)co-located images and binary assets
client-side search (elasticlunr.js)
what doesn't work yet
sass/scss compilation
zola image processing (
resize_image())load_data()from external URLsmultilingual sites (
default_languageconfig)
real example
the kanapka site is a live reference: kanapka.sublimated.com — a food blog with sections, author pages, image thumbnails, and responsive layout.