HTML Templates

HTML Templates

mbr uses Tera for templating. Customize any template by creating a file with the same name in your .mbr/ folder.

Template Files

TemplatePurposeWhen Used
index.htmlMarkdown page layoutRendering .md files
section.htmlDirectory listingSubdirectory pages
home.htmlHome pageRoot directory
error.htmlError pages404 Not Found, server errors

Partial Templates

Partials are prefixed with underscore and included by other templates:

PartialPurpose
_head.htmlBase <head> content
_head_markdown.htmlExtended head for markdown
_nav.htmlNavigation bar
_breadcrumbs.htmlBreadcrumb bar
_info_panel.htmlDocument info sidebar
_footer.htmlPage footer
_scripts.htmlBase JavaScript includes
_scripts_markdown.htmlMarkdown-specific scripts

Template Variables

Global Variables (All Templates)

These variables are available in all templates:

VariableTypeDescription
server_modebooltrue when running with live server (-s or -g), false for static builds
gui_modebooltrue when running in native window (-g), false for browser or static
relative_basestringPath prefix to .mbr/ assets (e.g., ../../.mbr/ for static builds)
relative_rootstringPath prefix to site root (e.g., ../../ for static builds)

Mode combinations:

Modeserver_modegui_mode
GUI (-g)truetrue
Server (-s)truefalse
Static build (-b)falsefalse

Markdown Pages (index.html)

VariableTypeDescription
markdownstringRendered HTML content
titlestringFrom frontmatter or filename
descriptionstringFrom frontmatter
datestringFrom frontmatter
tagsstringFrom frontmatter
breadcrumbsstringNavigation breadcrumbs HTML
headingsstringTable of contents data (JSON)
current_dir_namestringCurrent directory name
current_pathstringCurrent URL path
frontmatter_jsonstringAll frontmatter as JSON

Directory Pages (section.html, home.html)

VariableTypeDescription
current_dir_namestringDirectory name
current_pathstringDirectory URL path
parent_pathstringParent directory URL
breadcrumbsstringNavigation breadcrumbs HTML
subdirsstringSubdirectory list (JSON)
filesstringFile list (JSON)
is_homeboolTrue if root directory

Error Pages (error.html)

VariableTypeDescription
error_codenumberHTTP status code (e.g., 404)
error_titlestringShort error title (e.g., “Not Found”)
error_messagestringDetailed error message
requested_urlstringThe URL that was requested
breadcrumbsarrayNavigation breadcrumbs

File/Directory Data Structure

The files JSON array contains:

[
  {
    "url_path": "/docs/guide/",
    "name": "guide.md",
    "title": "User Guide",
    "description": "Getting started...",
    "date": "2025-01-09",
    "tags": "guide, docs"
  }
]

The subdirs JSON array contains:

[
  {
    "url_path": "/docs/",
    "name": "docs"
  }
]

Tera Syntax

Variables

{{ title }}
{{ markdown | safe }}  <!-- safe filter for HTML -->

Conditionals

{% if title %}
  <h1>{{ title }}</h1>
{% elif current_dir_name %}
  <h1>{{ current_dir_name }}</h1>
{% else %}
  <h1>Untitled</h1>
{% endif %}

Loops

{% for file in files %}
  <a href="{{ file.url_path }}">{{ file.title }}</a>
{% endfor %}

Includes

{% include "_head.html" %}

Common Gotchas

Chained Defaults Don’t Work

<!-- BAD: Fails if variable doesn't exist -->
{{ title | default(value=current_dir_name) | default(value="") }}

<!-- GOOD: Use conditionals -->
{% if title %}{{ title }}{% elif current_dir_name %}{{ current_dir_name }}{% endif %}

Check Variable Existence

{% if description %}
  <meta name="description" content="{{ description }}">
{% endif %}

JSON in JavaScript

<script>
  const frontmatter = {{ frontmatter_json | safe }};
  const headings = {{ headings | safe }};
</script>

JavaScript Configuration Object

The _head.html partial exposes a global window.__MBR_CONFIG__ object for use by JavaScript:

window.__MBR_CONFIG__ = {
  serverMode: true,     // false for static builds
  guiMode: true,        // true only in native window (-g)
  searchEndpoint: "/.mbr/search",
  basePath: ""          // relative path prefix for static builds
};

Use this in custom scripts to adapt behavior:

// Only show certain features in GUI mode
if (window.__MBR_CONFIG__?.guiMode) {
  // Native window - no browser URL bar visible
  document.querySelector('.url-display')?.classList.remove('hidden');
}

// Conditionally enable features requiring server
if (window.__MBR_CONFIG__?.serverMode) {
  initLiveSearch();
}

Example: Custom Page Template

Create .mbr/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  {% include "_head_markdown.html" %}
  <title>{% if title %}{{ title }} - {% endif %}My Notes</title>
</head>
<body>
  {% include "_nav.html" %}
  {% include "_breadcrumbs.html" %}

  <main class="container">
    <article>
      {% if title %}
        <h1>{{ title }}</h1>
      {% endif %}

      {{ markdown | safe }}
    </article>

    {% include "_info_panel.html" %}
  </main>

  {% include "_footer.html" %}
  {% include "_scripts_markdown.html" %}
</body>
</html>

Example: Add Analytics

Create .mbr/_footer.html:

<footer>
  <p>Built with mbr</p>
</footer>

<!-- Analytics (only in production) -->
{% if not is_dev %}
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'GA_ID');
</script>
{% endif %}

Example: Custom Navigation

Create .mbr/_nav.html:

<nav>
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/docs/">Documentation</a></li>
    <li><a href="/blog/">Blog</a></li>
  </ul>

  {{ breadcrumbs | safe }}

  <mbr-search></mbr-search>
</nav>

Example: Remove Breadcrumbs

Add an empty .mbr/_breadcrumbs.html.

Example: Directory Listing

Create .mbr/section.html:

<!DOCTYPE html>
<html lang="en">
<head>
  {% include "_head.html" %}
  <title>{{ current_dir_name }} - My Notes</title>
</head>
<body>
  {% include "_nav.html" %}

  <main class="container">
    <h1>{{ current_dir_name }}</h1>

    {% if subdirs %}
    <h2>Folders</h2>
    <ul>
      {% for dir in subdirs %}
      <li><a href="{{ dir.url_path }}">{{ dir.name }}/</a></li>
      {% endfor %}
    </ul>
    {% endif %}

    {% if files %}
    <h2>Files</h2>
    <ul>
      {% for file in files %}
      <li>
        <a href="{{ file.url_path }}">{{ file.title | default(value=file.name) }}</a>
        {% if file.description %}
          <p>{{ file.description }}</p>
        {% endif %}
      </li>
      {% endfor %}
    </ul>
    {% endif %}
  </main>

  {% include "_footer.html" %}
  {% include "_scripts.html" %}
</body>
</html>

Example: Custom Error Page

Create .mbr/error.html to customize the 404 and error page experience:

<!DOCTYPE html>
<html lang="en">
<head>
  {% include "_head.html" %}
  <title>{{ error_code }} - {{ error_title }}</title>
</head>
<body>
  {% include "_nav.html" %}

  <main class="container">
    <div class="error-page">
      <h1>{{ error_code }}</h1>
      <h2>{{ error_title }}</h2>

      {% if error_message %}
        <p>{{ error_message }}</p>
      {% endif %}

      {% if requested_url %}
        <p>Looking for: <code>{{ requested_url }}</code></p>
      {% endif %}

      <nav>
        <button onclick="history.back()">Go Back</button>
        {% if relative_root %}
          <a href="{{ relative_root }}">Home</a>
        {% else %}
          <a href="./">Home</a>
        {% endif %}
      </nav>

      <p>Try searching for what you need:</p>
      <mbr-search></mbr-search>
    </div>
  </main>

  {% include "_footer.html" %}
  {% include "_scripts.html" %}
</body>
</html>

Error Pages and Static Builds

When you build a static site with mbr -b, a 404.html file is automatically generated at the root of your output directory. This file is used by:

The generated 404.html uses relative paths so it works correctly regardless of where your site is deployed (root domain or subdirectory).

Important: In static mode, the requested_url variable is not available since the 404 page is pre-generated. The error page shows a generic message instead.

Development Workflow

  1. Copy the default template from mbr’s source
  2. Modify your copy in .mbr/
  3. Reload the page to see changes
  4. Use browser DevTools to debug

For rapid iteration, use the --template-folder flag:

mbr -s --template-folder ./my-templates ~/notes

This loads templates from an external folder, keeping your repository clean during development.