Glod is a static site generator, along the lines of Jekyll or Hugo. But way more spartan than either of those.
Project page: https://github.com/bcampbell/glod
A Glod site has a source directory structure something like this:
.
+-- site.toml overall site config
+-- skel/ css, js, images and other static files.
+-- templates/ default.html etc...
+-- content/ one file per page (markdown or html, with front
matter section for page-specific values)
Glod will copy skel
to www
, then add all the pages by processing the
content
files through templates.
Build from source:
$ git clone https://github.com/bcampbell/glod.git
$ cd glod
$ go install
$ glod [-server] [SITEDIR]
SITEDIR
is the top-level directory containing site.toml
. It may be omitted to operate upon the current directory.
The final website will be output to SITEDIR/www
.
-server
will cause glod to run a local web server to serve the site on. It will appear at http://localhost:8080
.
In -server
mode, altering any of the files will cause an automatic rebuild of the site.
eg - to build and run a local version of the glod website:
$ glod -server examples/glod
site.toml
This holds the overall site configuration.
The values in site.toml
are available for use in templates through the .Site
variable.
You can place any site-wide data you like in here, but there are a few names which have special meanings:
title
Fancy Site
“baseurl
http://glod.scumways.com
“pages
pages
in site.toml
, but it will be available for use in templates
via .Site
.an example site.toml
:
title = "Glod"
baseurl = "http://glod.scumways.com/"
When glod is run, it performs these steps:
site.toml
values into the .Site
collection.skel
to the output directory, www
content
:
.Page
collection..Page
and .Site
.www
, preserving the same directory structure as in content
.Each file in content
represents a single page.
Page content files can be markdown (.md
) or HTML (.html
) files.
They are processed through a template and rendered out to an .html
file.
Page-specific values can be defined in a front matter section.
The front matter is denoted by +++
. For example:
+++
title="Fancy blog post"
date="2011-02-05"
template="blogpost.html"
+++
Here is content for our fancy blog posting, in markdown.
... blah blah ...
The front-matter value template
specifies which template to use for the page.
If unset default.html
is assumed.
The directory structure in content
is preserved and will be reflected in the rendered website.
HTML files are passed through the template engine, and can access variables.
However the templates from the templates
directory are /not/ available here.
For example, you could generate an index page from an HTML content file like this:
+++
title="Index"
+++
<h2>Blog posts</h2>
<ul>
{{ range .Site.pages }}
{{ if in .path "blog" }}
<li><a href="{{.url}}">{{.title}}</a></li>
{{end}}
{{end}}
</ul>
Templates transform content into full pages.
Templates are written in the golang template format.
Templates can be for full HTML pages, or individual page components intended to be included from other templates (eg page headers and footers).
It’s up to you to decide how you want to organise them. You can use organise them in subdirectories, but remember that the template takes it’s name from the base filename, without the subdirectory. If multiple templates have the same name, only one of them will be defined.
For example:
header.html
:
<!DOCTYPE html>
<html>
<head>
<title>{{.Site.title}} - {{.Page.title}}</title>
<link href="style.css" rel="stylesheet"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<header class="site-header">
<h1>{{.Site.title}}</h1>
</header>
footer.html
:
</body>
</html>
default.html
:
{{template "header.html" .}}
<h2>{{.Page.title}}</h2>
{{.Page.content}}
{{template "footer.html" .}}
.Site
variableEverything in site.toml
is made available to the template through .Site
.
.Page
variableThis holds values specific to the current page being processed. It is initialised from the front matter section of the content file.
.Page
is really a shortcut to the entry in .Site.pages
for
the current page.
You can put any values you like in the front matter.
The names with special meanings:
title
hello-there
“
becomes “Hello There
”.date
template
default.html
).There are a few names which are not to be set in the front matter. They are derived values, calculated at runtime:
path
posts/april
The is taken directly from the path of the file within content/
.slug
everything-is-a-bit-shit
This is taken from the filename of the content file.url
/posts/april/everything-is-a-bit-shit
”).
There is a special case: if the slug is index
, then the url is truncated.
eg
index.html
” -> “/
”,posts/index.html
” -> “/posts/
“content
Various helper functions available within templates:
split [string] [sep]
Splits string
wherever sep
occurs, returning a slice containing the multiple pieces.
in [haystack] [needle]
Returns true if needle
is found in haystack
eg, generate a list of all pages under posts/
:
<ul>
{{ range .Site.pages }}{{ if in .path "posts/" }}
<li>{{ .date }} <a href="{{.url}}">{{.title }}</a></li>
{{ end }}{{ end }}
</ul>
sort [collection] <sortField> <sortOrder>
sorts collections (maps, arrays or slices) of elements
optional args:
sortField
sortField
lets you pick the one use as a sort key. (eg, you might sorts posts using "date"
). By default, maps are sorted by key and slices/arrays are sorted by value.sortOrder
TODO: examples
dateFormat [fmt] [date]
Formats the date
according to the fmt
string.
TODO: examples. Document fmt
.
It’s assumed that you have full control over how your web server maps URLs to pages.
Glod aims to produce nice clean urls like:
https://example.com/blog/example-post
…without the .html
suffix or any silly trickery like giving every page it’s own directory containing a single index.html
file.
The assumption is that you set up your web server to handle the pages correctly as html.
TODO: example configs for nginx and apache.
TODO: Should probably support an option for .html extensions or separate directories
server {
listen 80;
server_name example.com;
root /srv/example.com/www;
index index.html;
location / {
try_files $uri $uri.html $uri/ =404;
}
}
.Site.pages
Because of non-alphanumeric characters in keys, you’ll probably need to use the index
function in templates. eg:
This won’t work because of the ‘/’ and ‘-’:
<a href="{{index .Site.pages.docs/getting-started.url}}>Getting Started</a>
But this will:
<a href="{{(index .Site.pages "docs/getting-started").url}}>Getting Started</a>