Directory Configuration

2026-06-20

Directory-level configuration is declared in the folders field of __everkm/everkm.yaml. For config and default_template, see Site Configuration.

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

FieldTypeDefaultDescription
url_slugstringdirectory name slugifiedCustomizes the path segment name of this directory in URLs
hide_in_urlboolfalseWhen set to true, this directory is excluded from URL path concatenation
templatestringDefault template path for pages under this directory
queryobjectKey-value pairs merged into __qs during rendering
breadcrumbsarrayArray of breadcrumb entries, each containing title and url; supports @i18n:<key>
hash_scatterboolfalseWhether to scatter article URLs into subdirectories by hash (aliases: hash_storage, storage_scatter)
url_id_suffixbooltrueWhen set to false, non-index page URLs use {slug}.html without appending -{id}

Merge Rules

For an article located in a directory (e.g., /blog/2025/01/), configuration is merged along the ancestor chain (root → leaf):

Ancestor chain: / → /blog/ → /blog/2025/ → /blog/2025/01/
merged = defaults
For each level in chain: if folders[path] exists → merged.extend(folders[path])
  • 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

Merge Rules

  • "Home" is no longer automatically inserted at the beginning of the chain; if a home entry is needed, declare it in folders["/"].breadcrumbs yourself
  • When a subdirectory's breadcrumbs is 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)

Filename Rules

ConditionURL FilenameExample
Directory index pageindex/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 Example

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)

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 }}