bic is an opinionated and minimal static site generator—with a focus on
blogs. View the demo or the source.
It uses Pandoc to convert plain Markdown files into HTML. They get templated {{Mustache}}-style with Mo. Sqids is used to generate IDs.
You get the (opinionated) basics of a static site/blog (read: opinionated):
pages/about.md → /about.htmlposts/999-first-post.md → /first-post.htmldrafts/998-untitled.md → /drafts/untitled.htmlstatic/* → /*For reproducible builds, I would recommend using bic with Docker: ghcr.io/pinjasaur/bic:latest
Essentially, mount your source directory to /src
docker run --rm -v "$PWD":/src ghcr.io/pinjasaur/bic:latest
to spit out a build directory with your generated site.
Alternatively, bic is available as a nix flake.
Follow the setting up flakes guide to enable it, then run
nix run github:Pinjasaur/bic --command bic .
to run bic in the current directory and spit out a build directory with your
generated site.
bic is strict where necessary to keep it opinionated with a lean scope.
pages/*.md. Not nested.posts/*.md and drafts/*.md, respectively.
999-post.md
for the first post, 998-tacocat.md for the second, et cetera. I would
recommend 3 or 4 digits for the Future Proof™.mtime be used for the author’s discretion. However,
Git doesn’t record mtime, so I would treat it as the “last
modified” date.# to
signify the top-level heading.tags: foo, bar-baz./my-cool-post not /posts/2021/my-cool-post.html.For a fully-featured example, view the demo source code: https://github.com/Pinjasaur/bic-example
$ tree -F --dirsfirst
.
├── drafts/
│ └── 000-untitled.md
├── pages/
│ ├── about.md
├── posts/
│ ├── 998-foo-bar.md
│ └── 999-hello-world.md
├── static/
│ ├── css/
│ │ └── style.css
│ ├── img/
│ │ └── photo.jpg
│ └── js/
│ └── script.js
├── __feed.rss
├── __index.html
├── __tag.html
├── _footer.html
├── _head.html
├── _header.html
├── entry.html
├── feed.rss
├── index.html
├── page.html
├── robots.txt
├── sitemap.xml
├── tag.html
└── tags.html
bic uses an .env pattern. This lets you configure required variables and add
any extras that can be used within your templates. Talk about batteries included.
A .env file simply contains lines of KEY=value pairs. If you, for whatever
reason, want to supply an environment variable at runtime and have it
override your .env then use syntax such like:
ENV_VAR="${ENV_VAR:-default value}"
Not-100%-required but highly-recommended config:
SITE_AUTHOR e.g. Captain Anonymous (the site’s author)SITE_TITLE e.g., My Cool Thing (the site’s title)SITE_URL e.g., https://domain.tld (the site’s full base URL with no trailing slash)Optional, change if needed:
BIC_OVERWRITE (disable file overwrite protection, see #caveats, default: unset)BUILD_DIR e.g., _site (configure output directory, default: build)DATE_FORMAT e.g., +%B %d, %Y (passed into date, default: +%F → YYYY-MM-DD)TIMEZONE e.g., US/Central (the timezone you’re in, default: US/Central)Anything listed above or added additionally to a .env will be available
globally within templates.
Some specific keys used within entries (posts or drafts) and pages (except where noted):
slug, to be used in URL (does not contain the .html file extension)title, taken from first line of file # ...date, literally the mtime of the fileid, the number prefix for an entry (not page) encoded with Sqidsbody, converted Markdown to HTML contents (sans title)tags, list of all tags for the entry (not page)Drafts will have a draft key set. Likewise, posts will have a post key set.
Each entry in posts/*.md or drafts/*.md is rendered against an entry.html.
Each page in pages/*.md is rendered against a page.html.
index.html, feed.rss, and tag.html use a double-underscore-prefixed
template partial of the same name e.g., {{__index}} from __index.html.
tags.html has access to an associative array of all_tags where the keys are
the tags themselves and the values are the number of entries tagged by that tag.
sitemap.xml has access to an array of slugs with the slugs key.
There is an order-of-operations for how files are built, as follows:
pages/*.mdposts/*.mddrafts/*.mdindex.htmlsitemap.xmlrobots.txtfeed.rssstatic/* → /If you’re not careful, it’s possible you could overwrite an existing file e.g.
pages/test.md and posts/999-test.md both map to /test.html. bic uses the
Bash builtin noclobber e.g. set -o noclobber along with --interactive for
cp to protect against these scenarios. This can be disabled by setting
BIC_OVERWRITE. You’ve been warned.
bic in the wild:
bic is built & maintained by Paul.