A lightweight static site generator written in BoxLang. It converts Markdown (.md) and BoxLang markup (.bxm) files into a static website, with layouts, views, collections, tags, and pagination.
- Fast static builds with simple CLI (
build,list,help) - Markdown and BoxLang markup templates with YAML front matter
- Layouts, views, and partials in
_includes/ - Collections for pages, posts, tags, plus global JSON data from
_data/ - Permalinks, slugs, custom file extensions, and pagination
- Passthrough for assets and router files via
ssg-config.json
- BoxLang runtime and CLI (
boxlangon your PATH) - Required modules (managed via
requirements.txt):bx-jsoup,bx-markdown@1.0.0,bx-yaml
- Clone and enter the repo
git clone https://github.com/robertz/boxlang-ssg.git
cd boxlang-ssg- Install required modules
Use the helper script to read requirements.txt and install what’s missing:
boxlang setup.bxAlternatively, install manually:
install-bx-module bx-jsoup bx-markdown@1.0.0 bx-yaml- Build the site
boxlang ssg.bx buildGenerated files go to _site/ (configurable). You can serve _site/ with any static server. A simple router (router.bxs) is also copied into _site/ for BoxLang’s mini server setups.
boxlang ssg.bx build: Build the static site into the configured output folderboxlang ssg.bx list: List the discovered renderable documentsboxlang ssg.bx help: Show available commands
ssg.bx: CLI entry and build pipelinesetup.bx: Installs modules listed inrequirements.txtssg-config.json: Build configuration (output dir, passthrough, ignore)_includes/: Layouts, views, and partials_includes/layouts/main.bxm: Base HTML layout_includes/page.bxm,_includes/post.bxm,_includes/sidebar.bxm
_data/: Optional global JSON data (loaded intocollections.global)posts/: Example content (Markdown with front matter)assets/: Static assets (passthrough)router.bxs: Simple router included in output for dev servingindex.bxm: Example index page showing posts list404.md: Example 404 page (layout: none)
BoxLang SSG reads both .md and .bxm files. Each file may include YAML front matter to control metadata and output behavior.
Front matter markers:
- Markdown: start/end with
--- - BoxLang markup: start with
<!---and end with--->
Common front matter keys:
title: Page titledescription: Short descriptiontype: Content type (e.g.,page,post) — used for view fallback and collectionslayout: Layout file in_includes/layoutswithout extension (defaults tomain)view: View/partial in_includes/without extension; falls back totypeslug: Override file slug (used for posts)tags: Array of tags; buildscollections.tagsandcollections.byTagdate: Date the content refers topermalink: Override output path, e.g.,/tag/{{tag}}.htmlfileExt: Override output extension, e.g.,xmlpublished: Boolean to include/exclude from outputexcludeFromCollections: Boolean to skip item from collections
Example page (index.bxm):
<!---
type: page
layout: main
--->
<bx:output>
<bx:loop array="#collections.post#" item="post">
<a href="#post.permalink#">#post.title#</a><br />
</bx:loop>
</bx:output>Example post (posts/example.md):
---
layout: main
type: post
slug: my-first-post
title: My First Post
description: A short summary
tags:
- misc
published: true
---
# Hello
This is my first post.collections.all: All templates (except those excluded or parent pagination templates)collections.post: All items wheretype: post(sorted by date desc)collections.tags: Unique list of tags across postscollections.byTag[slug]: Posts grouped by slugified tagcollections.global: Nested structure built from JSON files in_data/(mirrors folder structure)
Use pagination in front matter with an alias and data source. The permalink should include {{alias}} to expand per page. See tags.bxm:
<!---
layout: main
view: page
permalink: /tag/{{tag}}.html
pagination:
alias: tag
data: collections.tags
--->In the view you can access prc.tag and iterate collections.byTag[slugify(prc.tag)].
{
"outputDir": "_site",
"passthru": ["router.bxs", "assets"],
"ignore": []
}outputDir: Build output directory (auto-cleaned each build)passthru: Files/directories copied verbatim intooutputDirignore: Additional paths to skip when discovering documents
Pull requests are welcome. For major changes, please open an issue first to discuss what you’d like to change.
MIT