tested on openbsd 6.8 with lowdown and macos 11.2 with Markdown.pl

make a static site with find(1), grep(1), and lowdown or Markdown.pl

ssg is a static site generator written in shell.

ssg converts markdown files to html with lowdown(1) or Markdown.pl, copies *.html files with <HTML> tag as they are. for the rest of .html files ssg extracts their titles from <H1> tag, prepends _header.html, appends _footer.html, copies from src to dst directory, and generates sitemap.xml, ignores files with name .* or listed in src/.ssgignore.


lowdown(1) and Markdown.pl are required if there are *.md files.

On OpenBSD:

$ mkdir -p bin
$ ftp -Vo bin/ssg https://rgz.ee/bin/ssg
ssg       100% |*********************|    4916      00:00
$ chmod +x bin/ssg
$ doas pkg_add lowdown
quirks-2.414 signed on 2018-03-28T14:24:37Z
lowdown-0.3.1: ok

Or on macOS:

$ mkdir -p bin
$ curl -s https://rgz.ee/bin/ssg > bin/ssg
$ curl -s https://rgz.ee/bin/Markdown.pl > bin/Markdown.pl
$ chmod +x bin/ssg bin/Markdown.pl


Make sure ssg and lowdown or Markdown.pl are in your $PATH:

$ PATH="$HOME/bin:$PATH"
$ mkdir src dst
$ echo '# hello, world!' > src/index.md
$ echo '<html><title></title>' > src/_header.html
$ bin/ssg src dst 'test' 'http://www'
[ssg] 1 files, 1 url
$ find dst
$ open dst/index.html

Markdown and HTML files

HTML files from src have priority over Markdown ones. ssg converts Markdown files from src to HTML in dst and then copies HTML files from src to dst. In the following example src/a.html wins:

src/a.md   -> dst/a.html
src/a.html -> dst/a.html

Incremental updates

On every run ssg saves a list of files in dst/.files and updates only newer files. If no files were modified after that, ssg does nothing.

$ bin/ssg src dst 'test' 'https://www'
[ssg] no files, 1 url

To force the update delete dst/.files and re-run ssg.

$ rm dst/.files
$ bin/ssg src dst 'test' 'https://www'
[ssg] 1 file, 1 url