yagss
is short for yet another generator of static sites. yagss
supports blogs and non-blogs. It uses Jinja style templates via pongo2, supports markdown (with code syntax highlighting from Chroma), RSS feed generation, cache-busting of static assets, and minifies output by default. Unlike Jekyll and Hugo, there are no themesβjust HTML templates and CSS, which you fully control.
yagss
is intended help make small, simple websites where all you really need is some HTML, CSS, and maybe a bit of JavaScript. It's not intended to replace more robust tools such as Hugo. See the quickstart and documentation below for more information.
See the releases page to download pre-compiled binaries for Linux and Mac.
To build from source, run these commands (you'll need go
and make
for this to work):
git clone [email protected]:AlexanderRichey/yagss.git
cd yagss
make install
yagss version
Usage:
yagss [command]
Available Commands:
build Build the current yagss site
help Help about any command
new Create a new yagss site
serve Serve the current yagss site and auto build when files change
version Print yagss version
Flags:
-h, --help help for yagss
Use "yagss [command] --help" for more information about a command.
$ yagss new demo
Creaing new yagss project in "demo"
==> Creating "demo" directory
==> Creating "demo/config.toml"
==> Creating "demo/posts" directory
...
==> Creating "demo/build" directory
Done in 1.694679ms
$ cd demo
$ yagss serve
----> Initial build
[builder] Starting build...
[builder] ==> Processing "public/favicon.ico"
[builder] ==> Processing "public/styles.css"
[builder] ==> Processing "posts/first-post.md"
[builder] ==> Processing "posts/forth-post.md"
[builder] ==> Processing "posts/second-post.md"
[builder] ==> Processing "posts/third-post.md"
[builder] ==> Processing "pages/about.md"
[builder] ==> Processing "pages/index.html"
[builder] ==> Processing "rss.xml"
[builder] Processed 9 files in 7.760285ms
----> Starting server and watcher
[watcher] Watching "pages" directory
[watcher] Watching "posts" directory
[watcher] Watching "public" directory
[watcher] Watching "includes" directory
[server] Listening on port :3000
# Now browse to http://localhost:3000
I recommend checking out the files, changing things, and seeing what happens.
Here's the yagss
directory structure and some information about each directory's role.
$ tree
.
βββ build
βββ config.toml
β # config.toml allows for controlling various build settings.
βββ pages
βΒ Β # The pages directory contains pages that can be in markdown or
β # html format. Pages can also use template directives and they
β # are compiled to the site's output directory.
βΒ Β βββ about.md
βΒ Β βββ index.html
βββ posts
βΒ Β # The posts directory contains markdown blog posts. Its usage is
β # optional.
βΒ Β βββ first-post.md
βΒ Β βββ forth-post.md
βΒ Β βββ second-post.md
βΒ Β βββ third-post.md
βββ public
βΒ Β # Files and sub-directories in this directory are moved to the root of
β # the output directory. Files that end with .html, .css, .js, .jsx,
β # .svg, .xml, or .json are automatically minified. If a file ends in a
β # extension specified in the build.hash array, then a hash will
β # be included in the outputted file's name.
βΒ Β βββ favicon.ico
βΒ Β βββ styles.css
βββ includes
# The includes directory contains templates and partials. Unlike
# pages, they are not compiled on their own. In other words,
# if a "includes/index.html" file exists, but no file in "pages"
# refers to it, then it will not be included in the site's
# output. In contrast, "pages/index.html" will be included.
βββ base.html
βββ page.html
βββ pagination.html
βββ post.html
5 directories, 13 files
Build the site with yagss build
. By default, generated files will be placed in the build/
directory. This can be changed by editing the directories.output
setting in config.toml
.
$ yagss build
Starting build...
==> Processing "public/favicon.ico"
==> Processing "public/styles.css"
==> Processing "posts/first-post.md"
==> Processing "posts/forth-post.md"
==> Processing "posts/second-post.md"
==> Processing "posts/third-post.md"
==> Processing "pages/about.md"
==> Processing "pages/index.html"
==> Processing "rss.xml"
Processed 9 files in 15.806605ms
Let's look at the generated files. Note that they are minified and that CSS assets contain hashes in their names. This makes cache-busting the default behavior. By default, hashes are added to .js
and .css
files. This can be changed by editing the build.hash
setting in config.toml
.
$ tree build
build/
βββ about.html
βββ favicon.ico
βββ index.html
βββ page2
βΒ Β βββ index.html
βββ posts
βΒ Β βββ first-post.html
βΒ Β βββ forth-post.html
βΒ Β βββ second-post.html
βΒ Β βββ third-post.html
βββ rss.xml
βββ styles.df1b98dd.css
Assets must be referenced in templates and markdown files with the assets
object and key
filter. assets
is a map of source-paths to output-paths, where its keys are source-paths of all files in the public
directory. assets
is made available to every template and markdown file.
$ cat includes/base.html | grep assets
<link rel="icon" href="{{ assets|key:'favicon.ico' }}" />
<link rel="stylesheet" href="{{ assets|key:'styles.css' }}" />
Pages must be placed in the directories.pages
directory and can be nested. The directory tree is preserved in the output. Posts can be in markdown or HTML format and can use template directives. Moreover, number of parameters described below are passed to page templates.
If pages are in markdown format, the defaults.pageTemplate
is used to render the page. This can be overridden by specifying a template
key in page's markdown front-matter whose value is a path to a template in the directories.includes
directory. Here's an example.
---
title: About
description: Optional description
template: "my-special-template.html" # Optional template override.
---
I am me--or am I?
And here's an example template:
{% extends 'base.html' %}
{% block content %}
<img src="{{ assets|key:'images/me.jpg' }}" alt="special image in this template">
<h2>{{ title }}</h2>
{{ content|safe }}
{% endblock %}
Note that content
, which is the rendered markdown content, uses the safe
filter. This is important because otherwise the rendered markdown would be escaped.
Blog posts must be placed in the directories.posts
directory (This can be changed in config.toml
). Each post must be a markdown file with front-matter that specifies a title and date, where any date's format is YYYY-MM-DD
. For example:
---
title: First post!
date: 2021-01-01
description: Optional description
---
![fireworks]({{ assets|key:'fireworks.jpg' }})
Hello world.
Note that the assets
object is made available to posts as well.
Blog posts are rendered using the defaults.postTemplate
file. A destructured post object and other fields are passed to this template. Here's an example of a defaults.postTemplate
that renders the given fields. Note that content
uses the safe
filter. As already mentioned, this is important because otherwise the rendered markdown would be escaped.
{% extends 'base.html' %}
{% block content %}
<h2>{{ title }}</h2>
<time datetime="{{ date }}">{{ date|date:"2 Jan 2006" }}</time>
{{ content|safe }}
{% endblock %}
The build.postsIndex
template file is used to generate a paginated list of all blog posts. A posts
object is passed to this template that contains all of the posts for the given page. next
and prev
strings are also passed to the build.postsIndex
template in order to support pagination. Page size is determined by the defaults.postsPerPage
setting. See below for a complete list of parameters passed to the posts index template.
Here's an example template:
{% extends 'base.html' %}
{% block content %}
<!-- Iterate through all posts -->
{% for post in posts %}
<article>
<h2>
<a href="{{ post.Path }}">{{ post.Title }}</a>
</h2>
<time datetime="{{ post.Date }}">{{ post.Date|date:"2 Jan 2006" }}</time>
</article>
{% endfor %}
<!-- Add links to next and prev pages, if there are any -->
{% if prev %}
<span>
<a href="{{ prev }}">Newer</a>
</span>
{% endif %}
{% if next %}
<span>
<a href="{{ next }}">Older</a>
</span>
{% endif %}
{% endblock %}
By default, an RSS feed is generated that uses the most recent build.postsPerPage
posts. If build.postsPerPage
is three, for example, then the most recent three posts will be included in the resulting rss.xml
. This can be disabled by making the build.rss
setting false
in config.toml
.
Field | Type | Comment |
---|---|---|
Title | String | Required. Passed from markdown front-matter. |
Description | String | Optional. Passed from markdown front-matter. |
Date | time.Time | Required. Passed from markdown front-matter. |
Content | String | Required. The rendered markdown. |
Path | String | Required. The relative URL of the post. |
URL | String | Required. The absolute URL of the post. |
Field | Type | Comment |
---|---|---|
pageTitle | String | The title of the page intended for use in the <title> tag. |
pageDescription | String | The description of the page intended for use in the description <meta> tag. |
siteURL | String | The base URL of the site. |
assets | Map | A map of source-paths to output-paths for all files in the directories.public directory. |
content | String | Optional. Rendered markdown from markdown file. |
title | String | Optional. Passed from markdown front-matter. |
Field | Type | Comment |
---|---|---|
pageTitle | String | The title of the page intended for use in the <title> tag. |
pageDescription | String | The description of the page intended for use in the description <meta> tag. |
siteURL | String | The base URL of the site. |
assets | Map | A map of source-paths to output-paths for all files in the directories.public directory. |
content | String | Optional. Rendered markdown from markdown file. |
title | String | Required. Passed from markdown front-matter. |
description | String | Optional. Passed from markdown front-matter. |
date | time.Time | Required. Passed from markdown front-matter. |
path | String | Required. The relative URL of the post. |
URL | String | Required. The absolute URL of the post. |
prevPost | Post | Optional. The next post ordered by the date field. |
nextPost | Post | Optional. The previous post ordered by the date field. |
Field | Type | Comment |
---|---|---|
pageTitle | String | The title of the page intended for use in the <title> tag. |
pageDescription | String | The description of the page intended for use in the description <meta> tag. |
siteURL | String | The base URL of the site. |
assets | Map | A map of source-paths to output-paths for all files in the directories.public directory. |
posts | []Post | An array of Post objects. |
next | String | Optional. Relative URL of the next page of posts. |
prev | String | Optional. Relative URL of the previous page of posts. |