DSG Dumb Site Generator :: 2024-01-22


Make your own static site generator in less than 100 lines of code.

(Or clone a template and hack it up how you like.)

This site is generated using a Dumb Site Generator pattern. (I'll explain...) Mine is 65 lines of dt source code. The language is early and a bit rough. If you're interested, take a look at the sources.

I liked the pattern, so I wrote a few more example static site generators as GitHub template repositories. Each is less than 100 lines of code. I'll explain what I'm up to first. The examples are at the end.

DSG - The Dumb Site Generator

The distilled form of DSG is to lay out website files like this:

├── index.html
├── style.css
├── ...more pages
├── page-list.html
└── blog
    ├── 2024-01-01-Some-post-title/index.html
    ├── ...more posts
    └── index.html (list)

And we generate that from sources laid out like this:

├── gen.script
├── site.html.template
├── Some-page-title.index.html.part
├── ...more pages
├── style.css
└── blog
    ├── 2024-01-01-Some-post-title.html.part
    └── ...more posts

site.html.template is the common header and footer content for all pages. The "ETC.part" files are partials. In the most basic uses of DSG, the content for the index.html page may be short enough that there is no need for a separate

The style.css is static css with no processing. It's intended to be linked from the site.html.template.

The "generator script" is some minimal script that does the following:

  1. Render pages. They should be in the format:
    with dashes substituted as spaces. (Hack on it! If you prefer another delimiter, do it. Same goes for everything else)
  2. Render each blog post. Use the site.html.template file and insert the title (from the filename) and the post content.
  3. Render a page listing and linking each blog post. If the post filenames are formatted as described below, a simple lexical sort can put them all in order.

If you can't get this done in your language in about 100~200 lines of code, something may be going wrong. Ask somebody for help!

We'll bake information into the filename that provides both the page titles and destination filenames. The title will come from the first section before a . character, and the destination filename will come from whatever immediately precedes the .html section. (If you choose a different markup language, adjust this accordingly.) We'll always translate dashes to spaces, except when the prefix looks like a date. The date thing sets you up for easy sorting of blog posts based on the prefix.

Here are some example filenames (IN) and what they should produce (DEST and TITLE).

  IN:    2024-03-07-My-first-example.latest.html.part
  TITLE: 2024-03-07 My first example
  DEST:  latest.html

  IN:    2024-03-07-My-second-example.html.part
  TITLE: 2024-03-07 My second example
  DEST:  2024-03-07-my-second-example/index.html

  IN:    My-third-example.i-am-number-3.html.part
  TITLE: My third example
  DEST:  i-am-number-3.html

  IN:    My-fourth-example.html.part
  TITLE: My fourth example
  DEST:  my-fourth-example/index.html

As we go, we'll either create an index.html file with a list of relative pages, or if an index.html page already exists, we'll create it as page-list.html.

By default, DSG uses html as the pre-processing markup language. Lots of people like to dog on HTML, and some even have valid points like Alan Kay, but HTML has remained the dominant markup language of the web for more than 30 years, so I'll assert it's a safe bet for a website.

Your DSG?

DSG is a very basic pattern with lots of opinions on everything. It's for the DIY crowd, so the idea is NOT that this is an optimal website layout. The idea is that this is going to be doing almost everything a basic website will need, and you can take the DSG idea (from a template?) and shape it into whatever you really want.

In other words, the DSG is like a seed. A do-it-yourselfer can take as a starting point, and nurture it over time into something more organic and personal. Or don't take a DSG at all, but just look at it and how it works and use that as inspiration that you can do this on your own.

Prefer some other format? Markdown, AsciiDoc, reStructuredText? Add that in. Prefer more page types, more templates, or a different layout? You got this. Go make a website without worrying about details of a website framework.

Quick Aside

With DSG I'm NOT trying to make any kind of statement about other static site generators. They are just for a different audience than the DIY kinda folks that this is for.

I've used a number of other SSGs, and fiddlier things like React, Vue, and Angular. I've been at this game for a while and have also used older things like WordPress, SharePoint, and Dreamweaver, and also more exotic things. None of these are quite what I want for my own simple sites, so I'm just going to make my own stuff and tailor it over time to the site.

Get Started

The canonical example and starting point template I'll recommend is this no-dependency DSG that uses only POSIX utilities. You don't even need bash or zsh.

Note: If you clone the template and choose to host it on GitHub Pages, enable the workflow that's included with the project. You may need to manually run it the first time from the repository's "Actions" if it ran and failed due to permissions.

For more DSG options in programming languages and markup languages, find (and please share!) DSG templates, example sites, and articles here:


How do I get updates over time?

The DSG is more of a minimalist starting place. DSG is not intended to be a dependency or a framework. Instead, it's intended to be small and simple enough that you can understand it, own it top-to-bottom, and do whatever you want with it.

"You're on your own" can be unsettling if you don't have experience with some of the technologies involved, and this is a goal of DSG. When a software owner is merging or responding to updates in a project's dependencies or its framework, the owner gets to have feelings of safety and progress without any incentive to grow skills or understanding. We should still share code and pool resources, but DSG is meant to be a statement and a reminder that these kind of transitive update activities can sometimes be solutions to problems that were completely unnecessary in the first place.

DSG templates may be tweaked over time to create a better starting place. Do NOT plan to merge future changes as "updates." Unless you're also trying to make a template for new sites, the goal of your website project should be to be a good website, it should not be a goal to be forever a good starting place. You are encouraged to hack up your site in ways that make it completely incompatible with any changes to a DSG template, it's your site, it's not a template. This is also a reason why DSG templates ship with as few dependencies and as few features as possible.

Why doesn't DSG do $feature?

Go ahead and do $feature in your site. It sounds like a great idea!

Instead of filenames, why not use a separate configuration file in $configlang for $data?

Go ahead, I've used $configlang too, and it's a great way to declare $data.