Overview
Zola is a fast static site generator written in Rust. It ships as a single binary with no dependencies, making installation and deployment simple. Zola includes built-in Sass/SCSS compilation, syntax highlighting, full-text search powered by Elasticlunr.js, image processing, and automatic sitemap/RSS feed generation. It uses the Tera templating engine (similar to Jinja2/Twig).
Zola is designed for speed and simplicity. It processes thousands of pages in milliseconds, supports content organization through sections and taxonomies, provides shortcodes for reusable content, and offers a live-reload development server.
Installation
# macOS via Homebrew
brew install zola
# Linux (Snap)
sudo snap install zola --edge
# Linux (Arch)
sudo pacman -S zola
# Linux (from binary)
wget https://github.com/getzola/zola/releases/latest/download/zola-v0.19.2-x86_64-unknown-linux-gnu.tar.gz
tar -xzf zola-v0.19.2-x86_64-unknown-linux-gnu.tar.gz
sudo mv zola /usr/local/bin/
# Windows (Chocolatey)
choco install zola
# Windows (Scoop)
scoop install zola
# Cargo (from source)
cargo install zola
# Verify installation
zola --version
CLI Commands
| Command | Description |
|---|
zola init my-site | Create a new site |
zola build | Build to public/ |
zola serve | Dev server with live reload |
zola serve --port 8080 | Serve on custom port |
zola serve --drafts | Include draft content |
zola check | Check for broken links |
zola build --base-url URL | Build with custom base URL |
zola build --output-dir dist | Custom output directory |
Project Structure
my-site/
├── config.toml
├── content/
│ ├── _index.md
│ ├── blog/
│ │ ├── _index.md
│ │ ├── first-post.md
│ │ └── second-post/
│ │ ├── index.md
│ │ └── photo.jpg
│ └── docs/
│ ├── _index.md
│ └── getting-started.md
├── sass/
│ └── style.scss
├── static/
│ └── img/
├── templates/
│ ├── base.html
│ ├── index.html
│ ├── section.html
│ ├── page.html
│ └── 404.html
└── themes/
Configuration (config.toml)
base_url = "https://example.com"
title = "My Site"
description = "A site built with Zola"
default_language = "en"
compile_sass = true
minify_html = true
build_search_index = true
generate_feeds = true
feed_filenames = ["rss.xml", "atom.xml"]
[markdown]
highlight_code = true
highlight_theme = "base16-ocean-dark"
smart_punctuation = true
external_links_target_blank = true
[search]
include_title = true
include_description = true
include_content = true
truncate_content_length = 100
[[taxonomies]]
name = "tags"
feed = true
paginate_by = 20
[[taxonomies]]
name = "categories"
feed = true
[extra]
author = "Your Name"
github = "https://github.com/username"
Content Frontmatter
Page Frontmatter
+++
title = "My Post Title"
description = "Brief description for SEO"
date = 2024-06-15
updated = 2024-06-20
draft = false
slug = "custom-url-slug"
weight = 10
template = "custom-page.html"
[taxonomies]
tags = ["rust", "web", "tutorial"]
categories = ["development"]
[extra]
author = "Jane Doe"
reading_time = "5 min"
+++
Content starts here...
Section Frontmatter (_index.md)
+++
title = "Blog"
description = "Latest posts"
sort_by = "date"
paginate_by = 10
template = "blog.html"
page_template = "blog-post.html"
insert_anchor_links = "heading"
+++
Sort Options
| Value | Description |
|---|
date | Sort by date (newest first) |
update_date | Sort by last update date |
title | Alphabetical by title |
weight | By weight field (ascending) |
slug | Alphabetical by slug |
none | No sorting |
Templates (Tera)
Base Template
<!DOCTYPE html>
<html lang="{{ lang }}">
<head>
<meta charset="UTF-8">
<title>{% block title %}{{ config.title }}{% endblock %}</title>
<link rel="stylesheet" href="{{ get_url(path='style.css') }}">
</head>
<body>
<nav>
<a href="{{ get_url(path='/') }}">Home</a>
<a href="{{ get_url(path='@/blog/_index.md') }}">Blog</a>
</nav>
<main>{% block content %}{% endblock %}</main>
<footer>© {{ now() | date(format="%Y") }}</footer>
</body>
</html>
Page Template
{% extends "base.html" %}
{% block title %}{{ page.title }} | {{ config.title }}{% endblock %}
{% block content %}
<article>
<h1>{{ page.title }}</h1>
<time>{{ page.date | date(format="%B %e, %Y") }}</time>
{% if page.taxonomies.tags %}
{% for tag in page.taxonomies.tags %}
<a href="{{ get_taxonomy_url(kind='tags', name=tag) }}">{{ tag }}</a>
{% endfor %}
{% endif %}
<div>{{ page.content | safe }}</div>
</article>
{% endblock %}
{% extends "base.html" %}
{% block content %}
<h1>{{ section.title }}</h1>
{% if paginator %}
{% for page in paginator.pages %}
<article>
<h2><a href="{{ page.permalink }}">{{ page.title }}</a></h2>
<p>{{ page.description }}</p>
</article>
{% endfor %}
<nav>
{% if paginator.previous %}<a href="{{ paginator.previous }}">Previous</a>{% endif %}
Page {{ paginator.current_index }} of {{ paginator.number_pagers }}
{% if paginator.next %}<a href="{{ paginator.next }}">Next</a>{% endif %}
</nav>
{% endif %}
{% endblock %}
Shortcodes
Built-in Shortcodes
{{ youtube(id="video_id") }}
{{ vimeo(id="video_id") }}
{{ gist(url="https://gist.github.com/user/gist_id") }}
Custom Shortcodes
<!-- templates/shortcodes/note.html -->
<div class="note {{ kind | default(value='info') }}">
<strong>{{ title | default(value='Note') }}:</strong>
{{ body }}
</div>
Usage:
{% note(kind="warning", title="Caution") %}
This is a warning message.
{% end %}
Image Processing
{% set image = resize_image(path="content/blog/photo.jpg", width=400) %}
<img src="{{ image.url }}" width="{{ image.width }}" height="{{ image.height }}">
| Operation | Description |
|---|
scale | Scale maintaining aspect ratio |
fill | Crop to exact dimensions |
fit | Fit within dimensions |
Deployment
# Build for production
zola build
# Netlify (netlify.toml)
[build]
command = "zola build"
publish = "public"
[build.environment]
ZOLA_VERSION = "0.19.2"
Troubleshooting
| Issue | Solution |
|---|
| Template not found | Check file is in templates/ with correct name |
| Content not showing | Verify _index.md exists in section |
| Sass not compiling | Ensure compile_sass = true; check SCSS syntax |
| Search not working | Set build_search_index = true; include search JS |
| Images not found | Use get_url() for paths; check static/ directory |
| Draft pages visible | Remove draft = true or use --drafts flag |
| Pagination not working | Set paginate_by in section frontmatter |
| Broken links in build | Run zola check to find and fix |