Directory-level configuration is written in the folders field: sites use __everkm/everkm.yaml; themes can preset defaults in everkm-theme.yaml (site overrides by path). For config, default_template, and overall ownership of the two files, see Site Configuration · Config Scope.
Subdirectory configuration is merged with inheritance from ancestor directories; deeper configurations override or append to shallower fields with the same name.
Since v0.17.0: The legacy per-directory index.yaml is deprecated and no longer read. Please migrate your configuration to everkm.yaml#folders.
Basic Example
# __everkm/everkm.yaml
folders:
"/":
hide_in_url: true
"/docs/":
template: book.html
query:
stack: true
breadcrumbs:
- title: "@i18n:nav.docs"
url: /docs/
"/blog/":
template: list.html
url_id_suffix: false
In templates, the merged query results are read via the global variable __qs; for breadcrumbs, see __breadcrumbs and nav_path.
Field Reference
| Field | Type | Default | Description |
|---|---|---|---|
url_slug | string | directory name slugified | Custom URL path segment; when explicitly set, the slug enters descendant article URL prefixes even if the directory has no index.md (see [[#url-generation |
hide_in_url | bool | false | When set to true, this directory is excluded from URL path concatenation |
template | string | — | Default template path for pages under this directory |
query | object | — | Key-value pairs merged into __qs during rendering |
breadcrumbs | array | — | Array of breadcrumb entries, each containing title and url; supports @i18n:<key> |
hash_scatter | bool | false | Whether to scatter article URLs into subdirectories by hash (aliases: hash_storage, storage_scatter) |
url_id_suffix | bool | true | When set to false, non-index page URLs use {slug}.html without appending -{id} |
Merge Rules
Config Sources and Priority
Same as config and default_template: theme folders as base, site everkm.yaml#folders overrides by path key. For deep merge of config (recursive objects, array replace), see Site Configuration.
effective_folders[path] =
everkm-theme.yaml#folders[path] (if present)
→ everkm.yaml#folders[path] non-empty fields extend override
On the same path key, if the site only sets template, theme preset fields like url_slug and url_id_suffix are still retained.
Theme developers preset routes and templates in everkm-theme.yaml; site operators only write deltas in everkm.yaml. See Theme Metadata.
Ancestor Chain Merge
For an article in a directory (e.g., /blog/2025/01/), merge along the ancestor chain (root → leaf) on effective_folders:
Ancestor chain: / → /blog/ → /blog/2025/ → /blog/2025/01/
merged = defaults
For each level in chain: if effective_folders[path] exists → merged.extend(...)
- Child-level explicit configuration overrides parent-level fields with the same name
- When a child level has no configuration, it inherits the merged ancestor result
- Merging follows ancestor chain order, not key string length sorting
Breadcrumbs
Merge Rules
- "Home" is no longer automatically inserted at the beginning of the chain; if a home entry is needed, declare it in
folders["/"].breadcrumbsyourself - When a subdirectory's
breadcrumbsis non-empty, entries are appended to the end of the ancestor chain by directory depth, rather than replacing the ancestor configuration entirely - When a subdirectory does not specify
breadcrumbs, it does not clear the already-merged breadcrumbs from ancestors - If no level has configuration, breadcrumbs are auto-generated based on the current page's URL path: each directory's index page appears in the breadcrumbs
The title field supports @i18n:<key> references. Only when the entry does not have url configured (or url is empty), a title of [[wikilink]] will be resolved as an inner link (i18n replacement happens first, then inner link evaluation), adopting the target page's title and URL.
folders:
"/":
breadcrumbs:
- title: "@i18n:nav.home"
url: ~/
"/blog/":
breadcrumbs:
- title: "[[blog]]"
- title: "@i18n:nav.blog"
URL Generation
Directory Path Concatenation
url_path = join(effective_slug at each level), skipping levels where hide_in_url == true
effective_slug = url_slug ?? slugify(directory segment name at this level)
Which directory segments enter the URL (either condition suffices):
- Explicit
url_slug: that level has a non-emptyurl_slugineffective_folders[path](including theme presets) - Directory index chain: that level lies on the path from root to the deepest directory
index.md(directory home); levels withouturl_sluguse slugified directory names
Intermediate levels without explicit url_slug and without any directory index on the ancestor chain do not appear in URLs (disk directory names are not leaked). Content can live under deep paths like /blog/2025/ while /blog/ uses url_slug: posts to map publicly to /posts/....
url_slug bypass is evaluated per path key and does not inherit to child directories. When parent /blog/ sets url_slug: posts, child /blog/2025/ without slug and without index does not push posts again.
Example (no directory index):
# theme or site folders
"/blog/":
url_slug: posts
| Article path | Logical URL |
|---|---|
/blog/2025/hello.md | /posts/hello-{id}.html (or hello.html; see url_id_suffix) |
If /blog/2025/ also has index.md, descendant URLs gain a /2025/ segment: /posts/2025/hello.html.
Filename Rules
| Condition | URL Filename | Example |
|---|---|---|
| Directory index page | index | /blog/index.html |
Normal page + url_id_suffix: true (default) | {slug}-{id} | /blog/hello-abc123.html |
Normal page + url_id_suffix: false | {slug} | /blog/hello.html |
Combined Examples
Directory partition + short URLs:
folders:
"/blog/":
url_id_suffix: false
hash_scatter: true
- Logical URL:
/blog/my-post.html - Export physical path:
/blog/ab/cd/my-post.html(triggered by__hs=1)
Decouple disk layout from public routes (common with theme presets + small site overrides):
# everkm-theme.yaml
folders:
"/":
hide_in_url: true
"/blog/":
url_slug: posts
template: list.html
url_id_suffix: false
# everkm.yaml (optional)
folders:
"/blog/2025/":
template: archive.html
/blog/2025/hello.md→/posts/hello.html(intermediate2025has no index and no slug, omitted from URL)
Navigation Functions and Inner Links
Book/document templates commonly use nav_tree, nav_path, and nav_indicator. If their from_file parameter is wrapped in [[...]], the same resolution rules as body inner links apply (case-insensitive, ambiguous links cause errors).
{{ nav_tree(from_file="[[./SUMMARY.md]]") | json_encode }}