SLAB is a tiny static-site generator demo built on top of:
- STDX (filesystem, strings, INI parsing, arena allocator, logging, etc.)
- Minima (embedded scripting language for templates)
markdown.h(Markdown → HTML conversion for.mdcontent)
At a high level, slab scans your content and theme folders, collects frontmatter metadata, builds a list of pages/categories, and renders each page by running Minima scripts embedded in HTML templates.
SLAB expects a site root directory passed on the command line:
slab <site_root>Inside <site_root>, it looks for _site.ini, then resolves:
content_dirtemplate_diroutput_dir- plus
nameandurl
from the [site] section.
The sample site (sample_site) uses:
content/for source contentthemes/default/for templates and static theme assetsdocs/as output
SLAB recursively scans both template_dir and content_dir.
- Paths beginning with
_are ignored during the recursive scan. - Files ending in
.md,.htm, or.htmlare treated as processable pages. - Everything else is copied to the output directory as static assets (images/css/etc).
For each processable file:
- It tries to parse frontmatter delimited by
--- ... ---. - If frontmatter is missing, the file is copied as-is (not templated).
- If frontmatter exists, SLAB builds a
SlabPageentry with metadata and output path.
After all pages are collected, SLAB derives a unique all_categories list from page metadata.
For each collected page:
- Read source content.
- If source is
.md, convert body (after frontmatter) to HTML. - Load the selected layout from
template_dir/_layout/<template>.html. - Expand template tags (
<% ... %>and<%= ... %>) into Minima code. - Execute that Minima code with variables injected into the global scope.
- Write generated HTML to
output_path.
Frontmatter is optional, but required if you want SLAB to treat a file as a templated page.
Expected format:
---
title: Hello
template: post
slug: posts/hello
date: 2025-03-17
category: post
tags: demo c
author: sailor
---
Markdown or HTML body starts here...
Recognized keys:
titleslugtemplatedate(parsed asyear/month/day)authortagscategory
Notes:
slugdetermines output file path (<output_dir>/<slug>.html).- If
dateis missing, file modification date is used. - Unknown keys are currently ignored (with debug print output).
SLAB templates are HTML files with embedded Minima code blocks:
<% ... %>→ statement block<%= ... %>→ expression block (auto-printed)
Examples from sample layouts:
<%= $post_title %>
<% foreach p $all_pages { print (page title $p) } %>
<% template (format "${template_dir}\\_include\\header.html") %>SLAB registers two custom Minima commands:
template PATH→ load and execute another template filepage PROPERTY PAGE_OBJ→ read properties fromSlabPage
Everything else comes from Minima builtins.
site_urlsite_nameoutput_dircontent_dirtemplate_dir
post_titlepost_datepost_yearpost_monthpost_daypost_slugpost_tagspost_authorpost_body
all_pages(list of page objects)all_categories(list of category strings)
Use page command to inspect each item in all_pages, e.g.:
(page title $p)
(page url $p)
(page category $p)
From repository root:
- Build
slab. - Run it against the sample site:
./demo/slab/bin/slab ./demo/slab/sample_siteExpected result:
- Generated HTML in
demo/slab/sample_site/docs - Copied static assets from
content/assetsandthemes/default/assets
You can then serve the docs/ folder with any static HTTP server.
- Files/folders starting with
_are excluded from directory scanning. - Pages without frontmatter are copied as static files.
- Layout file must exist at
_layout/<template>.htmlundertemplate_dir. - Markdown conversion only happens for
.mdpages. - Date parsing is forgiving; invalid month/day values are clamped to defaults with warnings.
- The
draftproperty exists onSlabPage/pagecommand but is not populated by frontmatter yet.