What is Firn?
Firn is a static site generator for org-mode. It is tailored for wikis, knowledge-bases, simple static sites &tc.
Firn is found under the snow that accumulates at the head of a glacier. It is formed under the pressure of overlying snow by the processes of compaction, recrystallization, localized melting, and the crushing of individual snowflakes.
Firn is currently being re-written. The below documentation refers to the new version.
Installation
Grab the latest release from the Github release page. Note: Downloading anything earlier than 0.15 will be an earlier prototype of Firn with a completely different API. Not recommended.
Quickstart
Install Firn wherever you like. Invoke it on a folder of org files:
# scaffold out a site: firn new # go explore what was generated: ls -la _firn # or maybe use tree, if you have it installed tree _firn # start a server and go looking for your files: firn serve # ready to build the output ? firn build
Usage
This section serves as the documentation for Firn. It's long, but it's all on one page (for now) so that you can easily search with your browser.
Front Matter
To use Firn, you will need to add some "Front Matter" to your org-files. Front Matter is common in many static-site-generators. Firn uses org-mode in-buffer-settings to set Front Matter.
The following front-matter are processed by Firn and/or made available to layouts for processing.
Key | Type | Purpose |
---|---|---|
#+title: | string | Required: Used in site-map, links, etc |
#+date_created: | org-mode-date | File date created |
#+date_updated: | org-mode-date | File last updated |
#+firn_tags: | list | Creates file based tags. |
#+firn_private: | boolean | Whether or not to read the file in question |
#+firn_sitemap: | boolean | Whether to include the file in the site-map. |
Note: for date_created
and date_updated
- you must use a full org mode date:
Good | Bad |
---|---|
<2022-01-15 Sat> | <2019-08-08> |
Currently, Firn requires that each file it processes at least have a #+title:
front-matter key value. But, you should consider adding a #+date_created and #+date_updated to each file, as it will enable ordering tags/posts, etc by date. (see the partial at _firn/layouts/partials/recent
for example).
Layout system
Tera
Firn uses Tera - a powerful templating engine similar to Jinja2. Out of the box, a new firn site will have some demo partials and layouts. Play around or read the documentation for Tera to see what you can do.
Layouts
Every org file you have should have a front matter for #+firn_layout
with a value of the name of a template file you have created. So, if you wanted a home page layout you would create the file _firn/layouts/home.html
, then in your org file (probably called index.org), add a front matter of #+firn_layout: home
. If you don't include a layout Firn will use the file located at _firn/layouts/default.html
.
Included Partials
When you create a new firn site, it will create a few demo partials that might be of use (backlinks, related files, recently published, sitemap).
These examples are then included into the default template.
Functions
Firn registers a few functions to the Tera templating language, allowing you to achieve specific template functionality.
Render
Render determines how you want to render org-mode content. Examples:
render() // render the whole file render(headline="Notes") // render everything started at the first headline of "Notes" render(update_level= 1) // bump all headlines up 1 level (h1 -> h2) render(update_level= -2) // bump all headlines down 2 levels (h3 -> h1)
Params | Type | Example |
---|---|---|
headline | string | "Notes" |
update_level | i8 | -2 |
Toc (Table of contents)
The toc()
function will render html for the pages table of contents. Because you may only be rendering a specific part of a file, the toc
function takes several optional parameters:
param | type | example |
---|---|---|
depth | integer | 3 |
headline_start | string | "Notes" |
exclude_root | bool | true |
list_type | string | "ul" |
depth: controls to what headline depth (h1 -> h6) you wish to render.
headline_start: select at which headilne to begin rendering table of contents items.
exclude_root: whether or not you wish to exclude the selected headline from headline_start from being rendered.
list_type: the type of list of html to render: a
<ul>
or an<ol>
.
Static files
When you run firn new
it will generate a static
folder at _firn/static/
. This is where you should put all your javascript, css, and fonts. When you build your site the static folder will be copied into the compiled site output at _firn/_site/static/
.
You will likely want to Link to these files in your layouts like so:
<html> <head> <link rel="stylesheet" href="{{config.site.url}}/static/css/main.css" type="text/css" media="screen" /> <script src="{{config.site.url}}/static/js/main.js"></script> </head> <!-- etc. .... -->
Custom Todo keywords
You can configure which TODO
keywords are recognized by Firn. Do this in _firn/config.yaml
.
When Firn parses your org files everytime it encounters one of these keywords, it will add a css class to the headline element created with the name firn_TODO
(where TODO, could be one of whatever keywords you use).
By default, Firn will not include the TODO
keywords you have selected in the actual headline. If you wish to do this, you'll need to use content
css tags to prepent/append the keywords as you see fit.
Sass
It's possible to write some Sass and have Firn compile it for you. To do this, navigate to <your_dir_of_org_files>/_firn/_sass.
and write some sassy css.
Firn will look for any file that is not prefixed with an _
(underscore) and compile it's contents, moving the output in _firn/_site/static
.
Note: You can configure whether you want to use scss or sass. Open up the _firn/config.yaml
file to change your prefrence.
Credit: I read a lot of Zola code to do the same thing, using their awesome work.
Tagging
Tagging is a bit complicated with Firn. Let's look at what data is available to work with and how you might used it.
Collected tag data
Your org files have headline tags - they look
:like: :this:
. These are "OrgTags". These are collected.Files that are processed by Firn can have a
#+firn_tags: ...
or#+roam_tags: ...
these are called "FirnTags" internally and are also collected.
On your site, you may wish to display either/any/all of these in your "Tag page". This makes navigating and exploring a site easier.
The [tag].html page
When you create a new Firn site, it generates a [tag].html
site. This is used as a template specifically for rendering a "tags" page, where the template engine inserts a list of tags that you can iterate and loop over. If that sounds confusing, you'll want to make sure you understand the template engine firn uses (Tera) and then go check out the [tag].html
file in the _firn/layouts
directory.
Remember, at any time you can add the tera context to the window object to inspect what data you have access to, so you can figure out how to iterate over that data:
<!-- in a template file --> <script>window.ctx = {{__tera_context}}</script>
Configuration
All configuration happens in _firn/config.yaml
. Please refer to that file as it is commented fairly heavily on what can be done.
Note: Removing keys from the default yaml file will break Firn - you need to have at least the base skeleton of the yaml keys present that come out of the box with Firn.
Roadmap
RSS
It's not yet clear how RSS should work. Previous versions of Firn used a css class to distinguish what content should be part of an RSS feed. To start the first implementation of RSS will probably just include the entirety of html content per page, sorted by date.
Logbooks
Firn captures logbook data but it is currently not accessible via the layouts. In the future there will be logbook data available in layouts for time tracking/time charts / heatmaps.
Linkgraph
Building an interactive link graph would be possible with Firn, as all links are captures and stored in memory when Firn runs. We may explore building this as a included javascript+html file.
Blogging
Firn cannot yet support rendering blog-series-posts from a single org-file, but this functionality is being planned for. This would allow one org file to spit out multiple html pages, as well as an "index" list for that specific blog.