Arrow

Arrow is a small personal site generator built to turn .djot files into .html files with minimal overhead. My site content is written in Djot with frontmatter for metadata.

Arrow takes in Djot files with following frontmatter fields title, description, date, CSS, JS, and status. It is injected into a single base template for all pages. Some pages might need custom CSS or JS, so the frontmatter includes CSS and JS fields to handle that. The status field determines whether a file gets built into HTML or not. I am using it to keep drafts out of the live site.

Arrow follows a fixed repository structure. The src/ folder is the only directory used for content. templates/layout.html is the base template for all pages. Assets are stored in src/assets/, and djot files referencing image.png should use /assets/image.png, not /image.png.

The output is placed in dist/, which is fully replaced on each build, so no important files should be kept there. Djot files from src/ are converted to HTML and placed in dist/ with the same structure, while src/assets/ is copied to dist/assets/. The dist/ folder is meant to be the root for deployment or live hosting, with all resource paths starting there.

Arrow does exactly what I need. It is not a general-purpose static site generator, nor does it aim to be. If your needs align with mine, it might be useful; otherwise, there are plenty of other tools out there.

usage

To start you should at minimum have the following directory structure

./src/assets/{keep your css, js, images here}
./templates/layout.html
                  # this is the main & only layout, you should keep it
                  # as minimal as possible. You can extend your specific
                  # pages with css & js files specific to that page

./src/{your djot files with your choice of structure.}

example layout.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta property="og:locale" content="en" />
    <title>{{ page.title | default(value="default title goes here") }}</title>
    <meta name="description" content="{{ page.desc | default(value="deault description goes here") }}" />
    <link rel="stylesheet" type="text/css" href="{{ page.assets_path }}/css/global.css"/>
    <link rel="icon" type="image/x-icon" href="{{ page.assets_path }}/img/favicon.ico" />
  </head>
  <body>
    <main>
      {{ page.content | safe }}
    </main>

    {% if page.inline_css %}
      <style>
        {{ page.inline_css | safe }}
      </style>
    {% endif %}
    {% if page.inline_js %}
      <script>
        {{ page.inline_js | safe }}
      </script>
    {% endif %}
  </body>
</html>

configuration

To create multiple sites & help arrow recognize them & also use some of the functionalities built into arrow, you need to declare a configuration file. The path for configuration files is as follows:

on Windows: ~/AppData/Roaming/arrow/arrow.conf

on Linux: ~/.config/arrow/arrow.conf or /etc/arrow/arrow.conf

The structure of configuration file is in YAML format and should be as following.

workspaces:
  # an example name for your workspace. the first entry is considered default
  site:
    # path to your workspace
    path: "/home/me/site"
  # another workspace called note
  note:
    path: "/home/me/notes"

# the default port on which localhost will serve your pages.
server:
  port: 4321

with the above config, running arrow serve -e note will build the djot files at /home/me/notes & serve it on localhost:4321.