+++*

Symbolic Forest

A homage to loading screens.

Blog : Posts tagged with ‘blogging’

No more cookies!

Or, rather, no more analytics

Regular readers—or, at least, people who have looked at this site before the last month or two—might remember that it used to have a discreet cookie consent banner at the top of the page, asking if you consented to me planting a tracking cookie that I promised not to send to anyone else. It would pop up again about once a year, just to make sure you hadn’t changed your mind. If you clicked yes, you appeared on my Google Analytics dashboard. If you clicked no, you didn’t.

What you probably haven’t noticed is that it isn’t there any more. A few weeks ago now, I quietly stripped it out. This site now puts no cookies of any sort on your machine, necessary or otherwise, so there’s no need for me to ask to do it.

When I first started this site’s predecessor, twenty-something years ago, I found it quite fascinating looking at the statistics, and in particular, looking at what search terms had brought people to the site. If you look back in the archives, it used to be a common topic for posts: “look what someone was searching for and it led them to me!” What to do when you find a dead bat was one common one; and the lyrics to the childrens’ hymn “Autumn Days When The Grass Is Jewelled”. It was, I thought—and I might not have been right about this—an interesting topic to read about, and it was certainly a useful piece of filler back in the days of 2005 when I was aiming to publish a post on this site every day, rather than every month. If you go back to the archives for 2005, there’s a lot of filler.

Now, though? Hopefully there’s not as much filler on the site as there was back then. But the logs have changed. Barely anything reaches this site through “organic search” any more—”organic search” is the industry term for “people entering a search phrase in their browser and hitting a link”. Whether this means Google has got better or worse at giving people search results I don’t know—personally, for the searches I make, Google has got a lot worse for the sort of searches where I didn’t know what site I wanted to go to beforehand, but for the sort of lazy searches where I already know where I want to go, it’s got better. I suspect the first sort were generally the sort that brought people here. Anyway, all the traffic to this site comes from people who follow me on social media so follow the link when I tell them there’s a new blog post up.

Given that the analytics aren’t very interesting, I hadn’t looked at them for months. And, frankly, do I write this site in order to generate traffic to it? No, I dont. I write this site to scratch an itch, to get things off my chest, because there’s something I want to say. I write this site in order to write this site, not to drive my income or to self-promote. I don’t really need a hit counter in order to do that. Morover, I realised that in all honesty I couldn’t justify the cutesy “I’m only setting a cookie to satisfy my own innate curiosity” message I’d put in the consent banner, because although I was just doing that, I had no idea what Google were doing with the information that you’d been here. The less information they can gather on us, the better. It’s an uphill struggle, but it’s a small piece in the jigsaw.

So, no more cookies, no more consent banner and no more analytics, until I come up with the itch to write my own on-prem cookie-based analytics engine that I can promise does just give me the sort of stats that satisfy my own nosiness—which I’m not likely to do, because I have more than enough things ongoing to last me a lifetime already. This site is that little bit more indie, that little bit more Indieweb, because I can promise I’m not doing anything at all to harvest your data and not sending any of it to any third parties. The next bit to protect you will be setting up an SSL certificate, which has been on the to-do list for some months now; for this site, given that you can’t send me any data, all SSL will really do is guarantee that I’m still me and haven’t been replaced, which isn’t likely to be anything you’re particularly worried about. It will come, though, probably more as a side-piece to some other aspect of improving the site’s infrastructure than anything else. This site is, always has been, proudly independent, and I hope it always will be.

A blast from the past

Or, digging out some old words

As it’s New Years Day, time for a new start and all that, I’ve … er … done what I said I was going to do back in November, and started to pull out posts from my previous blog, of twenty years ago, edit them and post them on here.

In my mind, this blog and that blog are effectively equivalent, so it’s strange to realise that I only kept that site going for two or three years or so. Compared to the not-quite-one-thousand posts on here, the old blog was hardly anything. Nevertheless, I still think it’s worth copying over some of the highlights, not that any of the handful of posts moved so far count as highlights. So far I’ve done March 2002, starting from the start, but starting a project is half the battle if you ask me.*

In the meantime, while I do more editing, there haven’t been many photos posted on here lately. So here’s one I uncovered on the old hard drive, from the Edinburgh period of my life. Going by the filename, this was taken in the Holyrood Tavern, which dates it to around 2003, before it changed hands and most of the regular clientele moved over to the Auld Hoose instead. I hope none of the people in the photo mind; but they’re probably a bit too blurry for a stranger to recognise them anyway.

Inside the Holyrood Tavern

Happy New Year!

* The Plain People Of The Internet: Is that why you never finish any?

A prelude

Or, some prehistory

A couple of times recently, I’ve mentioned that I’ve been pulling data off the hard drive of my old desktop computer, nested inside which was the home folders from the previous desktop computer, and nested inside those, those from the one before that. So, lots of rather old files to go through, and there will be more photos to post I promise. One thing I’ve uncovered that I didn’t think I had, though, was a text-only archive of the posts from my old blog.

Back in August I noted that this blog had turned sixteen. This was, in a way, a slight piece of misdirection. I had another blog before that, hosted by an online friend, which had run for a few years prior. Next spring, it will be twenty years since I started writing that site; it lasted just over three before, due to one reason and another, I dropped it and began this one.

Looking back at some of the posts, for the first time in a very long time, I’m slightly surprised by the tone of some of the writing. I had essentially no filter, and openly talked about exactly what I’d been doing, where I would be, visits to the doctor, what clubs and gigs I would be at, things I would never think of mentioning now. I refer to myself by name, which I never do now.

This blog, since its restart, has tended towards fairly long, rambling, in-depth posts in which I can go into a single topic in detail; and partly that’s down to its publish process, which makes it straightforward and simple* to host and manage, at a cost of being slightly clunky to add a new article. Every new post, essentially, requires the whole site to be re-uploaded so that the menus on every page are still correct, and that takes time to do. So, I don’t tend to write small posts. The old blog, managed using Movable Type, was full of one-liner diary entries about what I’d had for my tea, or what clothes I’d just bought.

Not all of the posts are like that, though; aside from some of the very personal things, there is for example a very fun and cheery account of my first proper trip abroad. I think I might actually get around to doing something I’ve been threatening to do ever since this blog first started. The first post on this site is itself a piece of misdirection, claiming to be a clean fresh start whilst at the same time saying that earlier writing might at some point make an appearance. If I can edit them into a format that fits this blog—changing people’s names to make them all consistent, bringing in The Plain People Of The Internet to handle the “fake outside reader” voice which was already occasionally present—without actually losing their style and flavour, I might some time soon get around to doing it.

* Not to mention cheap.

Another anniversary

A more recent one this time

A few weeks ago, I noted it was sixteen years since I first started writing this blog. Well, today, it’s a whole year since I relaunched it, as something of a lockdown exercise. It had taken most of my spare time in the summer, to go through all of the old posts, edit them, redesign the sight, and get the whole production pipeline up and running.

Since then there have been a hundred and forty-two posts, including this one; about mountains, beaches, trains, castles, cemeteries, trains, Lego, trains, computing, and trains. Have many people read them? No, probably not. That’s not really the point, though: not whether people read them, but whether I enjoy writing them. I have. So doing it has been worth it.

Despite it being the pandemic years, still, a lot has happened and a lot has changed over the past year. There will, I am sure, be more changes over the next year too. We won’t know, until they happen.

Little and often

Or, how often should a blog update, and does it really matter?

It’s almost the end of August, already.

If you ever scan your eyes down the list of links to the various archive pages on this blog—somewhere over on the right on desktop, right down the bottom on mobile, at least with the current design—you’ll see there were only five posts published here this month. Over the last three months in fact, there has been a bit of a drop-off in posting, compared to the other months since the blog was relaunched.

There are reasons for that, which I’m not going to go into here but which mostly involve having other outlets for my writing. Some of it might be published one day, and some won’t be, but that isn’t really the point of this post. The thing I wanted to talk about today is: does it really matter?

This initially popped into my mind at work a few months back, when I was preparing to interview a potential job candidate. Naturally beforehand I did all the usual background research on the candidate in question, looking at what social media profiles they had listed on their CV, hunting down some of the ones they hadn’t listed, and reading all the other links they’d put on their CV. The person in question included a link to a blog. When I followed it up, I found I really enjoyed the articles I found there (all of them tech-related in some way), but there were only a handful. This candidate had started a blog up in lockdown, had updated it a couple of times, and then nothing more. It was still sitting there on their CV, even thought it seemed to be getting a little bit cobwebby.

But does that matter? Well, frankly, it shouldn’t. If you’re interviewing a candidate for a job, you’re interviewing them, not their sticking power at a spare-time project. This blog, on the other hand, is never getting near anyone who might want to employ me, so it doesn’t matter at all if I go a little quiet for a few months, a few years, or even forever. It’s sad, a little, to see someone has started a project only to see it sputter out barely before it has started, but I should try to avoid letting it colour my opinion of them, particularly my opinion of them in a different context.

This site has been a little quiet, but it’s not as if I ever posted in any way consistently to begin with. It comes and goes according to my whims and inspiration, and whether or not I remember to write my ideas down. As I write it largely (but not entirely) for my own amusement, it shouldn’t really matter too much. I do gather information on how many people read this stuff, but I rarely actually look at that information. If I write anything for you specifically to read, I’ll tell you, but otherwise these words are just being thrown out into the electronic void. Some day, there might be an echo back, but I don’t really expect one.

A clean break

Well, not really

Back in the mists of time (well, January), I posted about the mechanism I use to keep track of ideas I’ve had for posts to write about, so I make sure that if I’m in the middle of something else and think “that would be a good blog post topic,” it doesn’t just get forgotten and allowed to wither.

I realised, looking the other day down the list of “tickets” for post topics to write about, that practically all of the things I actively want to write about are ideas I’ve come up with in the past couple of months, since moving house. There are plenty of things I wrote down before moving, but none of them really spark anything inside me at the moment, as something I want to put down and get out there. Some of them I do at least understand; others are a little bit more mystifying. When I put down a few words such as “Post about the fast-flowing water in Stockholm,” what did I really mean and what exactly was I going to say?

Moving house, it seems, has subconsciously been a much bigger upheaval than I realised it would be. A much bigger and cleaner break from the past than I was expecting. I can understand no longer having the energy to write posts about Bristolian local history; but all of those had been cleaned off the backlog already in any case. Somewhere in my head, all of the ideas I came up with before moving are now in a dusty mental box marked “do not need to unpack”.

Nevertheless, although I had a bit of a lull, there are now plenty of ideas to come. At some point, too, I’ll get back on to the old ones, maybe even finish writing that modern version of The Box Of Delights that I started to make a rough stab at. There is a lot more to say, even if as yet I don’t know exactly what all of it will be.

Cross-pollination

Or, some ideas for tracking ideas

A few days ago, I mentioned in passing that there I have lots of ideas for topics to write about on here, and the backlog of ideas is slowly building up. What I didn’t say was: how I track the backlog and remember all those ideas; instead, I thought to myself, that would make an interesting post for another day. “Backlog” isn’t meant to be derogatory, by the way. I see it as a good healthy thing, that I have lots of ideas that I haven’t as yet have had the time or energy or inclination to turn into words yet. Better that than a dearth of things I want to talk about, after all; that’s what would make this site slowly dry up and wither.

The Plain People Of The Internet: That and there not being any readers.

I don’t mind too much if there aren’t any readers. If I cared about readers I’d be cross-promoting this everywhere, doing complex deals and joint projects and promoting myself as the exciting new face of self-published diarising. I don’t, though, because the point of this is the writing, not the reading. But that’s by-the-by too really.

It’s very easy to get into the situation where ideas do just flit away on the wind as soon as they come along, and the spark of inspiration never gets turned into a post on here. Write your ideas down, is the standard piece of advice, but that means having something to write with, something to write on, and somewhere to collate and collect all of your scribbled notes. Working in software development, though, there are a few closely-related solved problems, so when I restarted this blog last summer I decided I was going to use the skills and tools I know from the day job to help me plan and track my writing on here. There are two key related tools that I’ve been using to help, which any software people reading this really should know about: version control and issue tracking.* If you are a software person, and you think the next paragraph is teaching you to suck eggs a little bit, then just remember that there are always people in the world who don’t know this stuff. Nobody is born with an innate knowledge of project management.

Version control is, very simply, the idea of keeping an archive of your working files that preserves their state over time, at least at the intervals you choose. It has a long history; the concept has been around probably longer than computers themselves. The leading system for it at the moment is called “git”, and was created by Linus Torvalds in order to help with development of his “Linux” operating system.** It effectively takes snapshots of all the files in a given folder at a point in time, and you can reset your “working copy” of the files to any snapshot whenever you want to. Moreover, each snapshot (or “commit” in the jargon) has a record of its parentage, and this ties commits together in a way that makes the folder’s history more than just one-dimensional. The chain of commits starting at a particular recent one and reaching back through the sequence of ancestral commits is called a “branch”; your archive can contain any number of named branches in parallel, and you can switch between branches whenever you want too. Not all developers really understand how to use branches properly, but if you do, they are a very powerful tool to help you organise disparate strands of work.

Git was originally designed to be a highly decentralised system without any single copy of the archive holding the privileged position of being the main primary copy. Most developers, however, don’t actually use it like that. A number of companies and organisations have sprung up to offer Git hosting services, and most development teams use one of these hosting services to host the primary copy of their Git data and use it as a centralised exchange point to share their code. That isn’t an issue for me writing this website, but these hosting services also offer additional services which are very useful: particularly, in the context of this post, ticketing systems. These are basically databases that let you create a “ticket”, generally some sort of work item such as a bug, a new feature or a task to be completed, and then let you track the progress of each one. The really fancy systems are so customisable you can completely shoot yourself in the foot designing over-complicated workflows, building reports, and adding custom data fields to each type of ticket, but I don’t care about any of that. The important thing here is that I can create a ticket, and I can access the “create ticket” function from anywhere through my phone. Whenever an idea for a new post comes along, I can immediately create a ticket with a brief description or title in it; then when I sit down to write something, I have a whole list of ideas I’ve had on the screen in front of me. Nothing gets forgotten, and all the ideas are there for me to come back to eventually, unless I didn’t put in enough of a description for it to make any sense.

When I start work on a post, I do exactly what I’d do when working on a piece of code. I read the ticket and click the button to flag it as in progress. I go to Git, make sure I’m at the tip of the “main” branch (as this reflects what’s currently on the website), and create a new branch with the ticket number in its name. I go into the site’s content code and create the new post, and when I’m happy with what I’ve written I create a commit with the new article in. Then, my Git hosting site has tools to help me check over what I’ve just done before folding those changes into the “main” branch. If I really wanted to, I could set up “continuous integration” code that would automatically push those changes out to the website as soon as they are folded into the main branch; although I’d use that for a software project, for this site I prefer to keep that process manual. When the changes have been made and the whole thing has been published, I mark the ticket as “closed”, and it disappears from my ticket backlog.

This sort of system isn’t for everyone, and it might not work for you, but I find it invaluable to keep track of what I’ve been thinking and what I’ve been planning. I find it’s fairly lightweight—it helps that I need to be comfortable with the tools anyway—but I understand not everyone is likely to agree. The hardest part, at least at first, is the discipline. Thinking to myself “better create a ticket for that” when an idea pops into my head, rather than just letting the idea float away again. Then again, that discipline is just as important if you rely on writing all your ideas down on paper; and the benefit of the technology is being able to easily file them all once you’ve done that. If anyone reading this is a non-tech person who has adopted these type of tools for non-tech activities like writing or indeed anything else, I’d love to know, and I’d love to know how much of a success it has been for you. For me, this is one big thing that helps me write, because it turns a lot of the administrative aspect of the writing process into something that is purely mechanical. For you, it might be different—but I’d love to know what you think.

* To be honest, there are a few software dev workshops that don’t use one or the other of those tools, even though they almost certainly should. They’re not new, and they make your life a lot easier. Even in top global businesses there are teams here and there who refuse to use version control, or more commonly, don’t really understand how to use it properly. It would be unprofessional of me to name and shame, but all I’ll say is, you would be surprised.

** This is not the place for a debate over whether Linux is an operating system or not.

We can rebuild it! We have the technology! (part four)

Or, finishing off the odds and ends

Settling down to see what else I should write in the series of posts about how I rebuilt this website, I realised that the main issues now have already been covered. The previous posts in this series have discussed the following:

And throughout the last two, we touched on some other important software engineering topics, such as refactoring your code so that you Don’t Repeat Yourself, and optimising your code when it’s clear that (and where) it is needed.

There are a few other topics to touch on, but I wasn’t sure they warranted a full post each, so this post is on a couple of those issues, and any other odds and ends that spring to mind whilst I am writing it.

Firstly, the old blog was not at all responsive: in web front-end terms, that means it didn’t mould itself to fit the needs of the users and their devices. Rather, it expected the world to all use a monitor the same size as mine, and if they didn’t, then tough. When I wrote the last designs the majority of the traffic the site was receiving was from people on regular computers; nowadays, that has changed completely.

However, the reason that this isn’t a particularly exciting topic to write about is that I didn’t learn any new skills or dive into interesting new programming techniques. I went the straightforward route, installed Bootstrap 4.5, and went from there. Now, I should say, using Bootstrap doesn’t magically mean your site will become responsive overnight; in fact, it’s very straightforward to accidentally write an entirely non-responsive website. Responsiveness needs carefully planning. However, with that careful planning, and some careful use of the Bootstrap CSS layout classes, I achieved the following aims:

  • The source code is laid out so that the main content of the page always comes before the sidebars in the code, wherever the sidebars are actually displayed. This didn’t matter so much on this blog, but on the Garden Blog, which on desktop screens has sidebars on both sides of the page, it does need to be specifically coded. Bootstrap’s layout classes, though, allow you to separate the order in which columns appear on a page from the order in which they appear in the code.
  • More importantly, the sidebars move about depending on page width. If you view this site on a desktop screen it has a menu sidebar over on the right. On a narrow mobile screen, the sidebar content is down below at the bottom of the page.
  • The font resizes based on screen size for easier reading on small screens. You can’t do this with Bootstrap itself; this required @media selectors in the CSS code with breakpoints chosen to match the Bootstrap ones (which, fortunately, are clearly documented).
  • Content images (as opposed to what you could call “structural images”) have max-width: 100%; set. Without this, if the image is bigger than the computed pixel size of the content column, your mobile browser will likely rescale things to get the whole image on screen, so the content column (and the text in it) will become too narrow to read.

On the last point, manual intervention is still required on a couple of types of content. Embedded YouTube videos like in this post need to have the embed code manually edited, and very long lines of text without spaces need to have soft hyphens or zero-width spaces inserted, in order to stop the same thing happening. The latter usually occurs in example code, where zero-width spaces are more appropriate than soft hyphens. All in all though, I’ve managed to produce something that is suitably responsive 95% of the time.

The other point that is worth writing about is the build process of the site. As Wintersmith is a static site generator, every change to the site needs the static files to be built and deployed. The files from the previous version need to be deleted (in case any stale ones, that have disappeared completely from the latest iteration of the output, are still lying about) and then Wintersmith is run to generate the new version. You could do this very simply with a one-liner: rm -rf ../../build/* && wintersmith build if you’re using Bash, for example. However, this site actually consists of three separate Wintersmith sites in parallel. The delete step might only have to be done once, but doing the build step three separate times is a pain. Moreover, what if you only want to delete and rebuild one of the three?

As Wintersmith is a JavaScript program, and uses npm (the Node Package Manager) for managing its dependencies, it turns out that there’s an easy solution to this. Every npm package or package-consumer uses a package.json file to control how npm works; and each package.json file can include a scripts section containing arbitrary commands to run. So, in the package.json file for this blog, I inserted the following:

"scripts": {
  "clean": "node ../shared/js/unlink.js ../../build/blog",
  "build": "wintersmith build"
}

You might be wondering what unlink.js is. I said before that “if you’re using Bash” you could use rm -rf ../../build. However, I develop on a Windows machine, and for this site I use VS Code to do most of the writing. Sometimes therefore I want to build the site using PowerShell, because that’s the default VS Code terminal. Sometimes, though, I’ll be using GitBash, because that’s convenient for my source control commands. One day I might want to develop on a Linux machine. One of the big changes between these different environments is how you delete things: del or Remove-Item in PowerShell; rm in Bash and friends. unlink.js is a small script that reproduces some of the functionality of rm using the JavaScript del package, so that I have a command that will work in the same way across any environment.

So, this means that in the main blog’s folder I can type npm run clean && npm run build and it will do just the same thing as the one-liner command above (although note that the clean step only deletes the main blog’s files). In the other Wintersmith site folders, we have a very similar thing. Then, in the folder above, we have a package.json file which contains clean and build commands for each subsite, and a top-level command that runs each of the others in succession.

"scripts": {
  "clean:main": "cd main && npm run clean",
  "clean:misc": "cd misc && npm run clean",
  "clean:garden": "cd garden && npm run clean",
  "clean": "npm run clean:misc && npm run clean:main && npm run clean:garden",
  "build:main": "cd main && npm run build",
  "build:misc": "cd misc && npm run build",
  "build:garden": "cd garden && npm run build",
  "build": "npm run build:misc && npm run build:main && npm run build:garden"
}

And there you have it. By typing npm run clean && npm run build at the top level, it will recurse into each subsite and clean and build all of them. By typing the same command one folder down, it will clean and build that site alone, leaving the others untouched.

When that’s done, all I have to do is upload the changed files; and I have a tool to do that efficiently. Maybe I’ll go through that another day. I also haven’t really touched on my source-control and change management process; and all I have to say there is, it doesn’t matter what process you use, but you will find things a lot more straightforward if you find a process you like and stick to it. Even if you’re just a lone developer, using a sensible source control workflow and release process makes life much easier and makes you less likely to make mistakes; you don’t need anything as rigid as a big commercial organisation, but just having a set process for storing your changes and releasing them to the public means that you are less likely to slip up and make mistakes. This is probably something else I’ll expand into an essay at some point.

Is the site perfect now? No, of course not. There are always more changes to be made, and more features to add; I haven’t even touched on the things I decided not to do right now but might bring in one day. Thoe changes are for the future, though. Right now, for a small spare-time project, I’m quite pleased with what we have.

Readers' Letters

Or, some of your questions answered

Time to answer some of the questions that have been sent in over the month or so since I revived this site.

Occasional reader Harold from Winchester read yesterday’s post about the Battle of Hastings and wrote:

Didn’t you write about that before?

Well, yes, it turns out that exactly ten years ago today I also wrote a “what might have happened if the outcome of the Battle of Hastings was different” post, including the same story of how the outcome was nearly different, and the side comments on how the battle has always been treated in English historiography. I suppose, if anything, it’s interesting to read the two side by side and see if my opinions have changed much over the past ten years, or if my writing style has evolved in the meantime too. Let me know if you think it’s better or worse than it used to be.

Regular reader Sarah from Ipswich writes:

Can I come with you on one of your trips to Wales?

Frankly, I wish I was going to Wales in the near future. All the nearby bits of Wales are closed to visitors at the moment, though. At some point I need to get myself back up to North-West Wales and visit the trains again, of course. Hopefully that will happen, even if it doesn’t now happen this year. As for the nearer bits of Wales: well, we’ll have to see how things progress I suppose.

And finally, long time reader E Shrdlu of Clacton writes:

Now you’ve brought this website back from the dead, are you still going to keep up the same running jokes and bring back all those series of posts you used to do years and years ago, like reviewing books you hadn’t finished?

Back in the mists of time I did indeed write reviews of books I hadn’t finished reading. I suppose you could call it a deconstruction of sorts, or an exercise in honesty, because they were at least all (I think) books I had tried to read, and failed to finish. Investigating why I failed to finish a particular book is interesting in itself, and admitting I didn’t finish it is more honest than just writing a review and saying “this is a bad book”. Moreover, if you read through those posts, you’ll see there were a broad range of different reasons for not finishing each book. One of them ended up being found by its author, who I had carefully not accused of plagiarism because I knew he was a former top barrister with lots more money than me.

I have to admit, I’m in the middle of drafting the next Books I Haven’t Read article. It’s probably going to be quite a long article, because it’s about quite a long book. I’ve also made sure it’s by a safely-dead author, so I can freely express my opinions about their poor understanding of archaeology or their failed attempt at polyamory. Feel free to guess who, and what, it’s going to be about; it’s a complex book, a complex topic, and it’s probably going to take me a while to finish it.

We can rebuild it! We have the technology! (part three)

Introducing Pug

If you want to start reading this series of articles from the start, the first part is here. In the previous part we discussed how I adapted Wintersmith to my purposes, adding extra page generators for different types of archive page, and refactoring them to make sure that I wasn’t repeating the same logic in multiple places, which is always a good process to follow on any sort of coding project. This post is about the templating language that Wintersmith uses, Pug. When I say “that Wintersmith uses”, incidentally, you should always add a “by default” rider, because as we saw previously adding support for something else generally wouldn’t be too hard to do.

In this case, though, I decided to stick with Pug because rather than being a general-purpose templating or macro language, it’s specifically tailored towards outputting HTML. If you’ve ever tried playing around with HTML itself, you’re probably aware that the structure of an HTML document (or the Document Object Model, as it’s known) has to form a tree of elements, but also that the developer is responsible for making sure that it actually is a valid tree by ending elements in the right order. In other words, when you write code that looks like this:

<section><article><h2>Post title</h2><p>Some <em>content</em> here.</p></article></section>

it’s the developer who is responsible for making sure that those </p>, </article> and </section> tags come in the right order; that the code ends its elements in reverse order to how they started. Because HTML doesn’t pay any attention to (most) white space, they have to be supplied. Pug, on the other hand, enforces correct indentation to represent the tree structure of the document, meaning that you can’t accidentally create a document that doesn’t have a valid structure. It might be the wrong structure, if you mess up your indentation, but that’s a separate issue. In Pug, the above line of HTML would look like this:

section
  article
    h2 Post title
    p Some
      em content
      | here.

You specify the content of an element by putting it on the same line or indenting the following line; elements are automatically closed when you reach a line with the same or less indentation. Note that Pug also assumes that the first word on each line will be an opening tag, and how we can suppress this assumption with the | symbol. You can supply attributes in brackets, so an <a href="target"> ... </a> element becomes a(href="target") ..., and Pug also has CSS-selector-style shortcuts for the class and id attributes, because they’re so commonly used. The HTML code

<section class="mainContent"><article id="post-94">...</article></section>

becomes this in Pug:

section.mainContent
  article#post-94 ...

So far so good; and I immediately cracked on with looking at the pages of the old Wordpress blog and converting the HTML of a typical page into Pug. Moreover, Pug also supports inheritance and mixins (a bit like functions), so I could repeat the exercise of refactoring common code into a single location. The vast majority of the template code for each type of page sits in a single layout.pug file, which is inherited by the templates for specific types of page. It defines a mixin called post() which takes the data structure of a single post as its argument and formats it. The template for single posts is reduced to just this:

extends layout
block append vars
  - subHeader = '';
block append title
  | #{ ' : ' + page.title }
block content
  +post(page)

The block keyword is used to either append to or overwrite specific regions of the primary layout.pug template. The content part of the home page template is just as straightforward:

extends layout
block content
  each article in articles
    +post(article)

I’ve omitted the biggest part of the home page template, which inserts the “Newer posts” and “Older posts” links at the bottom of the page; you can see though that for the content block, the only difference is that we iterate over a range of articles—chosen by the page generator function—and call the mixin for each one.

The great thing about Pug, though, is that it lets you drop out into JavaScript at any point to run bits of code, and when doing that, you don’t just have access to the data for the page it’s working on, you can see the full data model of the entire site. So this makes it easy to do things such as output the sidebar menus (I say sidebar; they’re at the bottom if you’re on mobile) with content that includes things like the number of posts in each month and each category. In the case of the tag cloud, it effectively has to put together a histogram of all of the tags on every post, which we can only do if we have sight of the entire model. It’s also really useful to be able to do little bits of data manipulation on the content before we output it, even if it’s effectively little cosmetic things. The mixin for each post contains the following Javascript, to process the post’s categories:

- if (!Array.isArray(thePost.metadata.categories)) thePost.metadata.categories = [ thePost.metadata.categories ]
- thePost.metadata.categories = Array.from(new Set(thePost.metadata.categories))

The - at the start of each line tells Pug that this is JavaScript code to be run, rather than template content; all this code does is tidy up the post’s category data a little, firstly by making sure the categories are an array, and secondly by removing any duplicates.

You can, however, get a bit carried away with the JavaScript you include in the template. My first complete design for the blog, it turned out, took something like 90 minutes to 2 hours to build the site on my puny laptop; not really helpful if you just want to knock off a quick blog post and upload it. That’s because all of the code I had written to generate the tag cloud, the monthly menus and the category menus, was in the template, so it was being re-computed over again for each page. If you assume that the time taken to generate all those menus is roughly proportional to the number of posts on the blog, O(n) in computer science terms (I haven’t really looked into it—it can’t be any better but it may indeed be worse) then the time taken to generate the whole blog becomes O(n2), which translates as “this doesn’t really scale very well”. The garden blog with its sixtyish posts so far was no problem; for this blog (over 750 posts and counting) it wasn’t really workable.

What’s the solution to this? Back to the Wintersmith code. All those menus are (at least with the present design) always going to contain the same data at any given time, so we only ever need to generate them once. So, I created another Wintersmith plugin, cacher.coffee. The JavaScript code I’d put into my layout templates was converted into CoffeeScript code, called from the plugin registration function. It doesn’t generate HTML itself; instead, it generates data structures containing all of the information in the menus. If you were to write it out as JSON it would look something like this:

"monthData": [
  { "url": "2020/10/", "name": "October 2020", "count": 4 },
  { "url": "2020/09/", "name": "September 2020", "count": 9 },
  ...
],
"categoryData": [
  { "name": "Artistic", "longer": "Posts categorised in Artistic", "count": 105 },
  ...
],
"tagData": [
  { "name": "archaeology", "count": 18, "fontSize": "0.83333" },
  { "name": "art", "count": 23, "fontSize": "0.97222" },
  ...
]

And so on; you get the idea. The template then just contains some very simple code that loops through these data structures and turns them into HTML in the appropriate way for each site. Doing this cut the build time down from up to two hours to around five minutes. It’s still not as quick to write a post here as it is with something like Wordpress, but five minutes is a liveable amount of overhead as far as I am concerned.

The Plain People Of The Internet: So, you’re saying you got it all wrong the first time? Wouldn’t it all have been fine from the start if you’d done it that way to begin with?

Well, yes and no. It would have been cleaner code from the start, that’s for certain; the faster code also has a much better logical structure, as it keeps the code that generates the semantic content at arm’s length from the code that handles the visual appearance, using the data structure above as a contract between the two. Loose coupling between components is, from an architectural point of view, nearly always preferable than tight coupling. On the other hand, one of the basic principles of agile development (in all its many and glorious forms) is: don’t write more code than you need. For a small side project like this blog, the best course of action is nearly always to write the simplest thing that will work, be aware than you’re now owing some technical debt, and come back to improve it later. The difficult thing in the commercial world is nearly always making sure that that last part actually happens, but for a site like this all you need is self-discipline and time.

That just about covers, I think, how I learned enough Pug to put together the templates for this site. We still haven’t covered, though, the layout itself, and all the important ancillary stuff you should never gloss over such as the build-deploy process and how it’s actually hosted. We’ll make a start on that in the next post in this series.

The next post in this series, in which we discuss responsive design, and using npm to make the build process more straightforward, is here