diff --git a/.gitignore b/.gitignore
index 44437cf7fe2b839a9bc40c397543fe20a7fa5899..364fdec1aa19d3a1f8d926d500c0beffe5674be8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1 @@
-site/
 public/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7faf8da8f447c26d813c7decab33499aaf3df42b..6a83ff75ec47ad2cbae67b60b669caeb8485964b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -23,22 +23,19 @@ pre-commit:
     - pre-commit run -a
 
 build:
-  image: python:3
+  image: alpine:3.13
   stage: build
 
   artifacts:
     paths:
-      - site
-
-  cache:
-    paths:
-      - .cache/pip
+      - public
 
   before_script:
-    - pip install mkdocs
+    - apk add --update zola git
+    - git submodule update --init
 
   script:
-    - mkdocs build
+    - zola build --base-url=/
 
 pages:
   image: alpine
@@ -52,8 +49,8 @@ pages:
     - master
 
   script:
-    # Gitlab will only expose files in a public folder at the root of the project
-    - mv site public
+    # Gitlab exposes files from the public folder at the root of the project
+    - 'true'
 
 # Deploy branches on Surge for testing
 .surge:
@@ -77,8 +74,7 @@ surge:
     on_stop: stop-surge
 
   script:
-    - mv site dist
-    - surge dist ${CI_ENVIRONMENT_URL}
+    - surge public ${CI_ENVIRONMENT_URL}
 
 stop-surge:
   extends: .surge
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..aace176a1898cf5a7df80294b15a86f42d3cf241
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "themes/book"]
+	path = themes/book
+	url = https://github.com/getzola/book.git
diff --git a/README.md b/README.md
index 2254d7b56d42d8390decd742f0903cbc1a514e9b..06ed9c06b9aa8c03a2258c050c77737c260d6b47 100644
--- a/README.md
+++ b/README.md
@@ -32,15 +32,14 @@ spelling mistakes, line endings, unmerged conflicts, etc.
 1. Run `pip3 install pre-commit`.
 2. Run `pre-commit install`.
 
-### Installing MkDocs
+### Installing Zola
 
-[MkDocs](https://www.mkdocs.org/) is the static site generator we use to build
+[Zola](https://www.getzola.org/) is the static site generator we use to build
 the docs as a website. You can install it and use it locally to see how your
 docs will look like.
 
-#### To install MkDocs
-
-1. Run `pip3 install mkdocs`.
+You can follow the [official setup instructions][zola-setup] to get Zola on
+your machine.
 
 ## Writing docs
 
@@ -51,16 +50,19 @@ To ensure we keep a consistent writing style, a style guide is available as
 
 ### Previewing your changes
 
-With MkDocs installed, you can display the resulting website locally and see
+With Zola installed, you can display the resulting website locally and see
 your changes be updated in real-time. A copy of the generated docs is also
 available online once you make your changes into a merge request on GitLab.
 
 #### To preview your changes locally
 
-1. Run `mkdocs serve` at the root of this repository.
+1. Run `zola serve` at the root of this repository.
+2. Open http://127.0.0.1:1111 in your web browser.
 
 #### To preview your changes in a merge request
 
 1. Push to GitLab and create a merge request.
 2. Wait for the CI pipeline to be successful.
 3. Click on the **View app** button to browse the generated docs.
+
+[zola-setup]: https://www.getzola.org/documentation/getting-started/installation/
diff --git a/STYLE.md b/STYLE.md
index 1eb1ac250858b9288d7f7c4e90847d329a46f41f..de1cea0be8cca50d89934a7913499fe27beb0dc7 100644
--- a/STYLE.md
+++ b/STYLE.md
@@ -293,6 +293,9 @@ sign:
 
 * One and only one first-level header should be included at the top of the page.
 
+  * The first-level header may be omitted if it is included by a static site
+    generator.
+
 * Increment header levels one at a time:
 
   ```markdown
@@ -569,6 +572,62 @@ one of the following:
 
 * Put this element in a separate document and always refer to it using links.
 
+## Project-specific guidelines
+
+This section describes guidelines that are purely specific to the Arkindex
+documentation; if this guide was to be copied for a different project,
+notably one using a different static site generator or different templates,
+those guidelines do not apply.
+
+### Front matter
+
+To learn more about front matter, see the Zola documentation for
+[front matter in pages](https://www.getzola.org/documentation/content/page/#front-matter)
+and [front matter in sections](https://www.getzola.org/documentation/content/section/#front-matter).
+
+* Always include front matter in all Markdown files.
+
+* Always include a `title` in all front matters.
+
+  * The `title` replaces the usual first-level Markdown header (`#`).
+
+* Always include a `weight` in all front matters.
+
+  * A new `weight` value should be the next available multiple of 10.
+
+    For example, if you had a page with weight 10 and one with weight 12,
+    the next page should have weight 20.
+
+  * If you run out of integer weights to insert a page in between two
+    pages, shift all of the other weights to become multiples of 10.
+
+* Prefer `draft = true` over `render = false` for draft pages.
+
+* For section indexes (`_index.md`), also include the following:
+
+  ```toml
+  sort_by = "weight"
+  insert_anchor_links = "right"
+  ```
+
+  > **Warning:** Sorting by weight means that pages without a weight will not
+  > be included in the HTML output.
+
+* Do not put any page outside of a section. Doing so can cause a strange error
+  with the current theme:
+
+  ```
+  Section `` not found
+  ```
+
+  For more information, see
+  [this GitHub issue](https://github.com/getzola/zola/issues/641).
+
+<!--
+TODO: Arkindex terminology guide, e.g. prefer "item" over "element" when it's
+not an Arkindex element
+-->
+
 ## Recommended reading
 
 * [Documentation Principles](https://www.writethedocs.org/guide/writing/docs-principles/)
diff --git a/config.toml b/config.toml
new file mode 100644
index 0000000000000000000000000000000000000000..e32364c4293af78bbab5eb21756e058997bfc632
--- /dev/null
+++ b/config.toml
@@ -0,0 +1,17 @@
+# The URL the site will be built for
+base_url = "https://doc.arkindex.org"
+
+# Whether to automatically compile all Sass files in the sass directory
+compile_sass = true
+
+# Whether to do syntax highlighting
+# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
+highlight_code = true
+
+# Whether to build a search index to be used later on by a JavaScript library
+build_search_index = true
+
+theme = "book"
+
+[extra]
+# Put all your custom variables here
diff --git a/content/_index.md b/content/_index.md
new file mode 100644
index 0000000000000000000000000000000000000000..3b1f29827e9eac71fbc3231fddb38b9529f39a8b
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,3 @@
++++
+redirect_to = "intro"
++++
diff --git a/docs/index.md b/content/intro/_index.md
similarity index 77%
rename from docs/index.md
rename to content/intro/_index.md
index 1b8e1d9258d335a37225529a50ccc0104bd7c837..c7fe125d44e9762e7530dd5b5d02ac37750ac93d 100644
--- a/docs/index.md
+++ b/content/intro/_index.md
@@ -1,4 +1,6 @@
-# Welcome to the Arkindex documentation
++++
+title = "Welcome to the Arkindex documentation"
++++
 
 This website provides user guides and reference for the
 [Arkindex](https://teklia.com/solutions/arkindex/) platform.
diff --git a/docs/intro.md b/content/intro/intro.md
similarity index 97%
rename from docs/intro.md
rename to content/intro/intro.md
index 9f343422b2830d4d1f9b8b1d5ca0fbc2c7e24240..416fc36182e4efe6fbbda92b2295db3d383829b3 100644
--- a/docs/intro.md
+++ b/content/intro/intro.md
@@ -1,4 +1,6 @@
-# Arkindex Intro
++++
+title = "Introduction to Arkindex"
++++
 
 ## Elements
 
diff --git a/mkdocs.yml b/mkdocs.yml
deleted file mode 100644
index 9302922947b8e3b847276b0900f5abbbb52cce78..0000000000000000000000000000000000000000
--- a/mkdocs.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-site_name: Arkindex Documentation
-docs_dir: docs
-theme: readthedocs
-
-nav:
-  - index.md
-  - intro.md
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..e6ae0af3f44a6e078300b7a2eef1346001827afd
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,45 @@
+{% extends "book/templates/index.html" %}
+
+{% macro toc(headers) %}
+    {% for header in headers %}
+        <li>
+            <a href="{{ header.permalink | safe }}">{{ header.title }}</a>
+            {% if header.children %}
+                <ul>
+                    {{ self::toc(headers=header.children) }}
+                </ul>
+            {% endif %}
+        </li>
+    {% endfor %}
+{% endmacro toc %}
+
+{% block menu %}
+    {% set index = get_section(path="_index.md") %}
+    {% for s in index.subsections %}
+        {% set subsection = get_section(path=s) %}
+        <li {% if current_path == subsection.path %}class="active"{% endif %}>
+            {% set chapter_num = loop.index %}
+            <a href="{{ subsection.permalink }}">
+                {% if config.extra.book_number_chapters %}<strong>{{ chapter_num }}.</strong>{% endif %}
+                {{ subsection.title }}
+            </a>
+            {% if subsection.pages %}
+                <ul>
+                    {% for page in subsection.pages %}
+                        <li {% if current_path == page.path %}class="active"{% endif %}>
+                            <a href="{{ page.permalink }}">
+                                {% if config.extra.book_number_chapters %}<strong>{{ chapter_num }}.{{ loop.index }}.</strong>{% endif %}
+                                {{ page.title }}
+                            </a>
+                            {% if current_path == page.path %}
+                                <ul>
+                                    {{ self::toc(headers=page.toc) }}
+                                </ul>
+                            {% endif %}
+                        </li>
+                    {% endfor %}
+                </ul>
+            {% endif %}
+        </li>
+    {% endfor %}
+{% endblock menu %}
diff --git a/themes/book b/themes/book
new file mode 160000
index 0000000000000000000000000000000000000000..acf1752a5f7a1257d28da2cbc591c2b8e8bc8ba8
--- /dev/null
+++ b/themes/book
@@ -0,0 +1 @@
+Subproject commit acf1752a5f7a1257d28da2cbc591c2b8e8bc8ba8