Writing a small static site generator in a day...


Why ?

I've always had problems with full blown blog systems whether they required to many resources or it took to long to implement simple features. So I took it upon myself to create a simple static-page generator in a day with a few goals:

First steps

After a few comparisons I settled for pug.js and started writing some node.js code to compile my pug files to html.

// get all posts
let posts = fs.readdirSync(postDir);
// for each post
for(let f of posts)
{
// compile the pug file
	let c = pug.compileFile(path.join(postDir,f,"/post.pug"),{pretty:true});
	let html = c();
	fs.writeFileSync(path.join(distDir,f+".html"),html);
}

That was easy!

browser-sync

Since I am not too familiar with pug and I always wanted to get my hands dirty with browser-sync I wrote a simple watch.js file which watches all files and runs a given task.

const bs = require("browser-sync").create();
const build = require("./build");

function fn(event, file) 
{
	// call the build script
	build();
	// forcefully reload the browser
	bs.reload();
}

// servce and watch for files
bs.init({
	server: "./dist",
	files: [
		{
			match:"./site/**/*.pug",
			fn: fn
		},
		{
			match:"./site/**/*.json",
			fn: fn
		}
	]
});

The above script and a simple task in the package.json now compiles all files, serves them on port 3000 and refreshes the browser whenever a file is changed.

metadata

Thanks to pugs templating system it supports a json which can be passed to the rendering function

let {title, description, keywords} = require("../site/posts/"+f+"/data.json");
let html = c({title, description, keywords});

So I can simply put all additional data I may need into the data.json and use its content in the pug template as variables.

New posts and Ids

To organize multiple posts and being able to creat an index page I came up with a simple Id system which takes the current time in seconds and converts it to a hex string.

let seconds = new Date().getTime();
// 1559384440202
let hexId = seconds.toString(16);
// '16b128e3d8a'

syntax highlighting

As an optional step for posts like this I wanted to have syntax highlighting and therefore added an assets folder which gets bundled and contains prism.js. So I easily include it via script tags.

Conclusion

This setup took me a good portion of an afternoon to finish but still leaves a few features open to finish like using templates for html meta-data and footer in pug and a cleanup of the js code. But all in all thats what I needed so ¯\_(ツ)_/¯