Making a sort of static site

Up until yesterday the public portion of my site (this blog and the couple of pages in the menu) was built using a combination of the Ghost platform for the blog and just straight up HTML for the other pages.

Oh and the post image has nothing to do with this post by the way, I just like it. I took it in Greece while we were travelling.

For the non blog pages the HTML (and CSS & JS) I wrote was served as written, with no build process, no nothing. I liked it that way. The blog used an early version of Ghost, which ran without issue for quite a while once set up. As a simple blogging platform I quite liked it, I think newer versions are more complete now (and in my view, perhaps worse for it) but the version I was using was super simple.

So if each bit of the site was good, why did I bother changing it? Especially since as far as I'm aware my site gets very little traffic (I don't know what it gets anymore, I removed Google Analytics ages ago)?

Largely because it felt like a site of two unnecessary halves. Pure static HTML on one side, with code repetition as it didn't even use server side includes for the menus and then the Node-based Ghost for the blog, running through a reverse proxy via .htaccess. It always bugged me that it was needlessly complex, despite the hard work having already been done and it running fine for years without issue.

KISS

In an effort to simplify, I first had to make things a little more complicated. I wanted to pull together both 'halves' of the (albeit, very small) site and manage them in the same way. I wanted to get rid of the need to run what amounts to a CMS for a simple blog.

But, equally, I didn't want to go down the path of Static Site Generators (SSGs) for this site. I've never yet actually have cause to use one, despite being aware of their many benefits. Like any tool, they can be great, but not all tools are right for all jobs – and the jobs I do benefit more from other tools.

The real downside of an SSG for me is that they require a literal build step of some kind (yes, this could be automated) to get the static part. This can give some real speed benefits and the general idea of SSGs lends itself to performance improvements.

But because a proper SSG generated site lives on the server as HTML files, there is no way to do server side things, like process forms or anything 'dynamic' (it's in the name), so numerous solutions are available to solve this problem. But these can let the complexity you were trying to avoid start to creep back in. Now your static site must be hooked up to an API to handle something a server side language could probably do without needing to rely on an external service.

Your SSG is simple once generated, but to get to that point you have probably had to install some tooling, some dependencies. Some of these dependencies probably have dependencies and now you've spent an hour getting them installed and Googling error messages, but it's fine, it's all working. You're a real developer.

Less tooling, more writing

Six months later you want to add a blog post, or a page to your static site. You write the content and run the build step but get an error message. An operating system update has broken your SSG, which in turn, you discover, has created a chain of broken dependencies which takes two hours to fix before you can finally push your new content to the server as a HTML file.

Or, you decide to forego the SSG in this case, for this and other reasons. You write your content, and put it on the server however you prefer and it just works. No build step, no dependencies. No having to open command line.

Sort of static

This new site, which looks almost no different to the previous version (except the fonts, which I'm still not sure about) now uses PHP, instead of a combination of pure HTML and the Node-based Ghost.

I looked into PHP based Static Site Generators, but concluded that none of them kept things quite as simple as I wanted to and that they still required dependencies and a learning curve which I couldn't be bothered with for this site.

So, stealing ideas from different places this site now uses;

  • Markdown files with frontmatter for the content. The content is authored in Markdown and stored on the server as a .md file.
  • PHP parses these files, using regex to split out the front matter to be parsed by the PHP YAML extension and the Markdown to be parsed by Parsedown, which is technically a dependency but it doesn't have any further dependencies itself and I've just included it 'the old way', I've just downloaded the file from GitHub directly.
  • The parsed frontmatter replaces snippets in the template files using a format stolen from various templating languages & static site generators with the variable surrounded by two curly braces.
  • The parsed Markdown replaces a curly brace snippet in the template file.
  • The page view template files have partials included using the same curly brace syntax.

Once this has all been processed by PHP (so it's not strictly static at all) the generated HTML file gets written to a folder (this is the static element, though really it's a cache).

If a generated static/cache file exists this is shown and the PHP code is never reached, thanks to a series of .htaccess rules, which first look for the static HTML file, then only if that isn't found pass the request to the PHP code (the code below is simplified).

// if the HTML file exists, then show that
RewriteCond %{DOCUMENT_ROOT}/site/static/%{REQUEST_URI}.html -f
RewriteRule ^(.*)$ /site/static/.html [NC,L,QSA]

// otherwise pass it over to be processed by the PHP script
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /site/index.php/ [NC,L,QSA]

So all that's needed for the static HTML file to be generated is for that page to be visited, which could be done as part of the PHP code by calling it via cURL, though I haven't yet implemented this and just visit the page manually.

I could also in theory generate all the static files using this cURL method and just upload the generated HTML to the server. The 'build step' being writing the content and visiting the page, then uploading the generated file to the server with no PHP needed on the actual server.

So it's a not static static site, using the ever unfashionable language PHP as the 'build step', which means I can't forget how to build the site, or fall into dependency hell.

Frameworks like Laravel, Static Site Generators like Hugo and CMSs like WordPress & Ghost absolutely have their benefits and fit a lot of projects well. But to meet my requirements for this site, rolling my own solution met them in the easiest way.

Those requirements are:

  1. Not require me to learn another language
  2. Not require me to 'install' something
  3. Not require a database
  4. Have no 3rd party dependencies (I understand that technically the whole stack is built from 3rd party dependencies, but I mean actual code decencies for the project, not for the infrastructure)
  5. Not require me to remember an obscure series of command line commands in six months time when I want to do something
  6. Not lock me in to 'their' way of doing things (I have other non public pages floating around which I don't want to have to hack around to get working alongside another platform)
  7. Have little to no learning curve to get a site running

So we'll see how it goes.