A tool for generating static websites.
b9407b37 — Zac Brown 28 days ago
Update dependencies.
94e5ccf5 — Zac Brown 5 months ago
Add a lint directive to Makefile
b955e624 — Zac Brown 5 months ago
Update deps.


browse  log 



You can also use your local clone with git send-email.


A simple, opinionated static site generator. This tool is designed explicilty for my own use. If it's helpful to you, great! I don't take feature requests but if you add a feature and think it'd be useful, I'll gladly accept patches.

The primary example of a site that uses this tool in its full form is available here: zacbrown.org-site


zsitegen is a simple site generator meant for blogs and personal web pages. It's explicitly designed to generate my own personal site. If it works for your purposes, great! I don't take patches, feature requests, or suggestion. If you find a bug and you believe it's important, I'd appreciate a heads up but I won't hold it against you if you don't tell me.

At the time of creation, it only supports four main features:

  • site index (menu/header)
  • pages - HTML pages without dates
  • posts - HTML pages ordered by date and included as part of the rss feed
  • tags - tags based on how posts are tagged
  • rss/atom/json feed

In the spirit of UNIX, everything is a file. There are a few files that inform the structure of the generated site:

  • ROOT/site.json - details about the site itself, including header and title
  • ROOT/menu.json - determines what pages are listed in the header
  • ROOT/style.css - a CSS file describing the style for each page
  • ROOT/index.md - the root landing page with some handy macros
  • ROOT/posts/posts.json - determines the order and date of posts
  • ROOT/pages/pages.json - determines the pages that are generated


The site.json file contains details about the site itself, including:

  • title
  • tag line
  • CSS stylesheet
  • preload content to inject into each page
  • the number of items to generate in the RSS/Atom/Json feed files
  • a list of folders of static elements to always copy into the target directory
    • This setting can be used to copy things over like static assets that you've checked into your project. For example, you could host your SSH public keys in a keys folder.

An example of this file:

    "title": "Zac Brown's Nonsense",
    "tag_line": "Occasionally useful, mostly useless",
    "stylesheet_file": "static/style.css",
    "preload_content_file": "link-preload.txt",
    "count_rss_atom_feed_items": 10,
    "author": "Zac Brown",
    "email": "some@email.com",
    "static_folders": [

The menu.json file specifies the pages to link, by name, in the "menu". The menu is displayed horizontally at the top under the header and tag line. At the time of writing, this logic is very dumb so it will add as many items as you specify.

Typically, the menu.json routes will refer to one of two things:

  • a page from the /pages route - e.g. pages/booklist.md
  • a route - e.g. /posts/

An example of the menu.json file:

        "label": "Home",
        "page": "/index.html"
        "label": "Pages",
        "page": "/pages/"
        "label": "Posts",
        "page": "/posts/"

        "label": "Tags", # This needs to be declared in the menu to ensure the tags can be generated.
        "page": "/posts/tags/" # This path is recommended, but not required.


style.css is just a plain CSS file describing the style for various elements. The stylesheet gets injected into every HTML page that is generated.


The index.md file represents the root file that will be transformed into index.html. By default, this will just be the content specified.

index.md will be rendered into the root index.html page including content or metadata from menu.json and site.json. Together, these three files specify the root index structure.

Possible Expansions:

  • a macro to include N most recent blog posts


The posts/posts.json file specifies the posts that are published into the /posts route of the site. If you don't specify a markdown file in the posts/posts.json file, then it will not be rendered and added to the posts/index.html rendered file.

The order of posts/posts.json is parsed from oldest to newest. The oldest posts are at the top of the file, and the newest posts are at the bottom of the file. Note that this only impacts the order in which the posts are rendered. The date metadata attached to a post is independent of order.

An example of the posts.json file:

    "title": "A Basic Golang Project Template",
    "path": "2021-02-19-golang-template.md",
    "date": "2021-02-19",
    "tags": ["howto", "programming"]


The pages/pages.json file specifies the pages to render from markdown into HTML under the /pages route. These pages are intended for more static content like a book list or "about me" page. The /posts/index.html will be rendered with pages listed in the order listed in the pages/pages.json file.

    "title": "Books",
    "description": "books I've read worth further consideration",
    "path": "books.md"

#Site Generation Algorithm

zsitegen always performs the same operations in the same order. There's no caching done and existing files will be overwritten in the output directory.

#Site-wide Descriptors

These files are used to construct every page, so they're read and validated first. style.css gets no validation - it just gets copied to the output directory and linked into each page.

Pages for the site are constructed using the composition of:

  • menu.json - the menu descriptors
  • site.json - the overall site descriptors

#Index, Pages, and Posts

The pages and posts are loaded in the order they're specified in the respective json files.

The processing algorithm follows the same path:

  • pages/pages.json is processed and each page is generated
  • posts/posts.json is processed and each post is generated
  • index.md is processed, and the index page is generated