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.html
posts/999-first-post.md
→ /first-post.html
drafts/998-untitled.md
→ /drafts/untitled.html
static/*
→ /*
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/*.md
posts/*.md
drafts/*.md
index.html
sitemap.xml
robots.txt
feed.rss
static/*
→ /
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.