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