A Markdown site in Everlock is a Git repository. Every file you push is either served directly, rendered as a page, or used as site infrastructure. This page explains what each file and directory does, why it exists, and how Everlock treats it.
The rules described here only apply to sites running in markdown mode. In html mode, all files are served as-is and none of this structure is interpreted.
Top-level overview
A minimal but fully functional site might look like this:
More complex sites add data/, format variant templates, and additional section directories.
site.toml — site-wide configuration
site.toml at the root configures global metadata and structural behavior. Everlock reads it on every request; you do not need to restart to see changes.
Items per page on list pages; omit to disable pagination
sitemap
Set to true to serve /sitemap.xml; defaults to false. Requires base_url for correct absolute URLs
nav.links
Navigation items available to templates as site.nav.links
markdown.syntax_highlighting
Toggle code block syntax highlighting
markdown.highlight_style
Name of a Syntect highlight theme
taxonomies
Custom taxonomy fields; each key maps a URL prefix to a frontmatter field
ignore_dirs
Root-relative directories to skip when scanning markdown and serving files; defaults to []
site.toml is internal infrastructure. It is never served over HTTP.
Ignored directories
In markdown mode Everlock automatically skips any path component that starts
with a dot (for example .git/, .cursor/, .venv/). Files under those
directories never become pages, never appear in section listings, and are not
served as static assets.
Use ignore_dirs to extend that filter to non-hidden directories — typical
candidates are generated output folders or vendored dependencies you keep in
the repo for tooling but do not want published:
reads docs/_index.md for the section title and intro
lists all child .md files in docs/ as a generated page index
uses the layout: from _index.md (or falls back to list.html)
never exposes _index itself as a link in the listing
Example _index.md:
---
title: Documentation
layout: blog_list
---
The full reference for running and extending Everlock.
Without a _index.md, the section title defaults to the URL path and no intro text is shown. The listing still works.
Choosing a section layout
By default, section listings use list.html. To use a different template, set layout: in _index.md:
---
title: Project updates
layout: blog_list
---
This tells Everlock to render the /updates/ listing with layouts/blog_list.html instead of layouts/list.html. The blog_list.html template receives the same page, pages, and pagination context variables as list.html.
Regular content pages
Any .md file that is not index.md or _index.md becomes a content page at a URL derived from its path:
Subdirectories become URL segments automatically. You do not need to register routes.
Frontmatter
Every page can have a YAML frontmatter block at the top:
---
title: My page title
date: 2026-01-15
tags: [guide, setup]
categories: reference
draft: false
layout: article
description: A short description for search and meta tags.
series:
- getting-started-series
my_custom_key: some value
---
Page content starts here.
Field
Meaning
title
Page title shown in <title>, headings, and listings
date
Publication date; used for sorting and RSS
tags
List of tags; powers /tags/ routes automatically
draft: true
Hides the page from listings, search, RSS, and direct access
layout
Template name (without .html) inside layouts/; defaults to single.html
description
Per-page meta description; falls back to site.toml description
series
List of series names this page belongs to; enables prev/next navigation
Any key not in the set above becomes an extra field available to templates as page.extra.your_key.
Any key whose value is a YAML list of strings becomes available as page.extra_lists.your_key. This is how series and custom taxonomies work.
Draft pages
Setting draft: true excludes the page from all generated output: it will not appear in listings, the search index, RSS, sitemaps, or tag pages. It is also not accessible over HTTP directly.
---
title: Work in progress
draft: true
---
Content here is invisible until draft is removed.
<!--more--> — the read-more split
Placing the HTML comment <!--more--> inside page content splits the page into a visible summary and the rest of the article. The content before <!--more--> becomes the page summary available to templates and is used in listing cards.
---
title: My article
---
This paragraph is the summary. It appears in listing views.
<!--more-->
This paragraph and everything after it only appears on the full page.
layouts/ — templates
The layouts/ directory holds Tera templates that control how pages are rendered. Every file in layouts/ is registered as a template, using its path relative to layouts/ as the name. The file extension is the output format — .html for web pages, .vcf for vCards, .json for JSON, etc.
layouts/
├── base.html ← outer shell: <html>, <head>, <body>, nav, footer
├── single.html ← individual content pages
├── list.html ← section listings and tag pages
├── search.html ← the /search page
├── blog_list.html ← example: a custom blog-style section listing
├── person.html ← example: HTML layout for a contact page
└── person.vcf ← example: vCard format variant for the same page
layouts/ and its contents are never served over HTTP.
base.html
The outer HTML shell. All other templates typically {% extends "base.html" %} and fill in a {% block main %} block. base.html has access to site and page context variables.
single.html
Used for individual content pages. Receives:
Variable
Content
page.title
Page title from frontmatter
page.content
Rendered HTML of the page body
page.tags
List of tag strings
page.date
Frontmatter date
page.git_date
Date of last git commit for this file
page.summary
Rendered HTML of content before <!--more-->
page.related
Up to 5 pages sharing tags with this page
page.prev_page
Previous page in the same series, if any
page.next_page
Next page in the same series, if any
page.extra
Map of scalar extra frontmatter fields
site
Parsed site.toml
list.html
Used for section listings, tag pages, and taxonomy pages. Receives:
Variable
Content
page.title
Section title (from _index.md or path)
page.content
Rendered HTML from _index.md body
pages
List of child page objects, each with title, url, tags, date, git_date
pagination
Pagination object (only present when paginate_by is set)
site
Parsed site.toml
A custom section listing template such as blog_list.html receives exactly the same variables and can be selected via layout: in _index.md.
Format variants
A format variant lets a single Markdown file be served in multiple content types. The page declares a layout: in its frontmatter; Everlock uses that name as the template family and the requested file extension to pick the right template.
---
title: Alice Example
layout: person
---
With this frontmatter:
/contacts/alice renders layouts/person.html → HTML page
There is nothing special about the name assets/. Any directory that contains files without a .md extension will have those files served directly. assets/ is simply the conventional name.
images/ — image files
Images and other media live in images/ by convention and are served directly:
The data/ directory holds .toml files that are loaded and made available to all templates as the data context variable.
data/
├── team.toml
└── releases.toml
data/team.toml:
[[members]]
name = "Alice"
role = "Maintainer"
[[members]]
name = "Bob"
role = "Contributor"
In any template:
{% for member in data.team.members %}
<li>{{ member.name }} — {{ member.role }}</li>
{% endfor %}
Only top-level .toml files in data/ are loaded. Subdirectories are ignored. data/ is never served over HTTP.
Auto-generated routes
Everlock generates several routes automatically for every Markdown site. These do not need any files in the repository.
Route
Content
/index.xml
RSS feed of all pages, sorted by date
/sitemap.xml
XML sitemap of all pages with last-modified dates (only when sitemap = true in site.toml)
/search
Search page (requires layouts/search.html)
/search-index.json
JSON search index consumed by the search page
/tags/
Tag listing page
/tags/<tag>
Pages matching a specific tag
Custom taxonomy routes are also generated automatically based on site.toml:
[taxonomies]
category = "categories"
This generates /category/ and /category/<value> routes for any page with a categories: frontmatter field.
Internal paths — never served
These paths are reserved for site infrastructure. Requests to them return 404 regardless of what exists in the repository:
Path
Purpose
site.toml
Site configuration
layouts/
HTML templates
shortcodes/
Shortcode templates
data/
Data files for templates
Series — prev/next navigation
Pages can be linked into an ordered series using the series: frontmatter list. All pages sharing the same series name are sorted by date ascending, and each page gets prev_page and next_page context variables pointing to its neighbors.
Every page automatically gets a related list in its template context. Everlock finds up to five other pages that share tags with the current page, ranked by the number of tags in common. No configuration is needed; it follows from your tag usage.
{% if related %}
<aside>
<h3>Related</h3>
<ul>
{% for p in related %}
<li><a href="{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
</ul>
</aside>
{% endif %}
Full example: a blog
Here is a concrete repository layout for a simple blog, with annotations showing what Everlock does with each file:
Visiting /posts/ renders a blog-style index using blog_list.html, with each post listed by date and title. The _index.md controls the section heading and which template is used. Each post file is a regular content page served by single.html.