Why build my own static site generator?¶
This blog has been an exercise in learning JavaScript. Previously I was building static pages using Hexo with the Next theme (the look of this blog has many elements of the Next theme copied).
Hexo has so many features and special effects which is cool, but also confusing. I wasn't able to easily customise it - like for the main pages which aren't part of my blog, or for displaying Jupyter Notebooks which I use a lot for making notes when learning new things.
As Hexo is just a static page site generator, I decided to build my own very simplified version of it. This way I would know how every part of it worked and have complete control to make it look how I wanted. I've lost a couple of features that I can one day add back in, such as comments from Disqus, and Google Analytics tags applied to each page, also I lost all the animations. But now I can post any custom type of page I like and have made code to convert Jupyter Notebook's and display them nicely.
The Structure¶
The main components of the site are split into templates and use a library called Mustache
to piece them together to create my static site.
I have a bunch of partials
that sit in their own folder - like the header and nav bar that appear on every page, and the navigation footer that is at the end of every post.
I have three main templates
at the moment which are the main types of page I might display, these are my main pages - simple pages that only contain the header and nav bar, my archive page that lists all blog posts, and my blog-post pages which includes the nav footer.
As I create new posts and pages I add them to a source
directory and reference them in a config file
which is basically just a big JSON object. The config contains the page title, type, post-date, and path to source file.
Finally there is the script! The script reads loads all templates in the partials
and templates
directories, then loops through the config generating a new page for each entry, placing them in a public
folder.
There are also additional files to be copied to the public folder like css
,images
,pdfs
,js
etc
blogPosts.js // Config file of blog posts to be generated
siteGenerator.js // Script to be run in Node to convert all content into HTML
/ partials
header.mustache
footer.mutache
/ templates
mainPage.mustache
archive.mustache
blogPost.mustache
/ source
/ images
/ pdfs
/ blogPosts
myNotebook.html
/ public
...
Mustache¶
There's not much to building Mustache
templates, they're just HTML with a few additional tags for places to insert partials or variables. Here's a few examples of the different things you can insert:
Strings¶
Double-curlies
var titleVarName = "Home Page"
example.mustache
:
<html>
<head>
<title>{{titleVarName}}</title>
</head>
<body>
...
HTML¶
Triple-curlies
var mainContentHTML = "<p>Welcome to my website<br/>Take a look around</p>"
example.mustache
:
...
<body>
{{{mainContentHTML}}}
</body>
</html>
Partials¶
Partials can be templates so need to be handled differently to HTML in order for variables to be passed into them.
var headerPartial = "<div>Welcome {{name}}. This is the header partial!</div>"
example.mustache
:
<body>
{{> headerPartial}}
...
</body>
Links¶
To avoid url escaping make sure to include ampersand:
example.mustache
:
...
<link>
{{& linkPath}}
</link>
...
Mustache Rendering¶
const template = fs.readFileSync(templatePath).toString()
const contentVars = {'title': 'Archives', 'homePageLink': '/', 'contentHTML': contentFromFile}
const partials = {'header': headerFromFile, 'footer': footerFromFile}
const renderedHTML = Mustache.render(template, contentVars, partials)