Skip to content

Folia 0.1.0

The first pre-1.0 release of Folia, the Rust static-site generator behind ggirelli.info.

Read this first. 0.1.0 is a release of the software: it builds the reference site, its checks pass, and it refuses to destroy what it did not write. It does not mean the Jekyll site has been replaced, or is ready to be. Folia's output equals Jekyll's for most outputs and differs, on purpose or known, for the rest; the site's owner decides whether that is enough for publishing it. Folia is also fully vibe coded: tested, not audited, and provided without warranty. It is built for one website and is not a general-purpose static-site generator.

What it is

folia build reads a site (a git repository of Markdown and HTML sources, templates and a configuration) and writes the static site to a directory.

Content it builds

Kind What
Pages Markdown and HTML pages with explicit permalinks, redirects (redirect_from, as stubs and redirects.json), tables of contents, covers, an error page
Blog posts dated by file name, categories, tags, previous and next, the paginated index with featured posts, one archive per category, the categories and tags pages
Microblog notes, likes, bookmarks and RSVPs, each with its own template, and listings that claim a page and list entries
Digital garden notes with wiki-links, backlinks and the note graph (notes_graph.json)
Assets static files copied as they are; Sass stylesheets compiled with Dart Sass, with source maps

Documents without a title are titled as Jekyll titles them. Front matter Folia does not know is refused rather than ignored.

Generated outputs

  • Feeds: Atom feeds for the blog, each tag, micro entries (and each kind), the garden, and a combined feed, written as jekyll-feed 0.17 wrote them.
  • Sitemap: sitemap.xml, as jekyll-sitemap 1.4 wrote it (the URL set is the same; the order and static files' lastmod differ, see below).
  • Search: the search script's documents array, followed by the site's own code.

Using it

folia build --site path/to/site --dest path/to/out        # --config defaults to <site>/_folia/folia.toml
folia --version
  • Configuration: _folia/folia.toml in the site (time-zone, exclude, [site], [roots], [authors.*], [micro], [garden], [blog], [feeds], [search], [sass]); the public example site shows each table, and Architecture describes them. A key Folia does not know is an error.
  • Prerequisites: to build Folia, a stable Rust toolchain (edition 2024) and git; to build a site with Sass stylesheets, Dart Sass exactly 1.100.0 (sass on PATH or FOLIA_SASS); to run the checks, just, uv, Node.js, Ruby with Bundler, Python 3 and cargo-deny. The manual testing guide lists the commands that installed all of it on a fresh Ubuntu 24.04. There is no prebuilt binary and no crates.io release: build from source (cargo build --release -p folia).
  • Templates are MiniJinja and strict: a template that reads a value a page does not have is an error, not an empty string.

Safety guarantees

These are tested with unit tests and with the real binary (crates/folia/tests/cli_safety.rs).

  • --dest is written only if it is absent, empty, or a directory a previous Folia build wrote (a record beside it names it and lists what it held). Anything else (your files, a moved copy, a directory with something added) is refused and nothing in it is touched. Folia never deletes what it did not write, and refuses leftover temporary directories rather than removing them.
  • The output is built beside the destination and swapped in last, so a failed build leaves the previous output exactly as it was.
  • A missing or failing template, a render error or an unknown author fails the build with every problem listed, naming the template and the pages. Nothing is skipped silently: only documents Folia does not support yet are skipped, and each is named.
  • Exit status: 0 built, 1 the build failed (nothing written), 2 usage or configuration error.

Known limitations and intentional differences from Jekyll

Documented in full in Known limitations. In short:

  • Exact parity with Jekyll is not reached, and is not claimed. The parity tooling separates a clean build (every output accounted for) from exact parity (every output identical), and a documented difference is not identical output. Most outputs are identical or differ only as the owner approved; some differ on purpose or are known.
  • On purpose: feed <updated> is the newest item's date, not the build time; the sitemap lists pages by URL and dates static files by their last commit; the search index includes micro entries and joins no words across line breaks (an improvement on Jekyll's); category and tag pages do not link feeds that never existed; a tag with a space gets a feed.
  • Not built yet: page types other than Markdown and HTML, Liquid in HTML pages, last_modified_at on pages; syntax highlighting uses syntect, not Rouge (the token classes differ in some blocks).
  • Source defects it reproduces, such as links written without a scheme, are recorded by the site's owner, not guessed at.

Verification at release

Unit and integration tests, just check (formatting, clippy pedantic, tests, docs, cargo deny, linters, negative checks of the parity scripts, the docs build) and CI on Ubuntu; the example site builds and serves from a clean Ubuntu 24.04; a real site builds deterministically (two builds are byte-identical) and its Markdown output matches Jekyll's apart from documented differences.

Documentation

Home, Development setup, Manual testing (install, build, serve, troubleshooting), Known limitations and How it is made.