A Signal in the Static

About a year ago I set out to rebuild my site, and being reared on PHP I opted to go for Craft CMS while it was in beta. I figured it’d be interesting to learn it while it was still in development, and maybe create my own plugins.

Haha. Jokes. I did not. I tried, though, but never really needed anything extra.

I was also using Laravel Forge to automatically deploy whenever I pushed any changes to the master branch. To this day it’s still a nice approach, but there’s a lot of moving parts. I have a repo, a server that needs to be looked after (like when I updated PHP and broke everything), a database that needs to be backed up, and a CMS with some plugins that need to be kept up to date. Granted, I could not have touched it after day 1 and it would still work just the same, but that’s not me. If it ain’t broke, go fix it.

That’s where the allure of a static site generator comes in. As far as the site goes, everything is in one place. Content lives in Markdown files which makes things pretty portable. I landed on using Hugo after seeing some recommendations for it, and in about a day I had my entire site copied over, including CSS and JS. To copy the content I took advantage of the Element API plugin for Craft to get a JSON object of all my posts. The config file for the plugin looked like this:


use craft\elements\Entry;
use craft\helpers\UrlHelper;

return [
  'endpoints' => [
    'posts.json' => [
      'elementType' => Entry::class,
      'criteria' => ['section' => 'posts'],
      'transformer' => function(Entry $entry) {
        return [
          'title' => $entry->title,
          'url' => $entry->url,
          'date_published' => $entry->postDate->format(\DateTime::ATOM),
          'slug' => $entry->slug,
          'body' => $entry->postContent,
          'categories' => $entry->categories->all()

So when it hit https://my-site.com/posts.json it returned everything I needed. I saved this to a file to quickly generate markdown versions like so:

const posts = require('./data.json')
const fs = require('fs')

function buildCategory({ title }) {
  return `- ${title}`

function buildFrontMatter(post) {
  return `---
title: "${post.title.replace(/"/g, '\'')}"
date: ${post.date_published}
draft: false
categories: \n${post.categories.map(buildCategory).join(`\n`)}

posts.data.forEach(post => {
  let content = `${buildFrontMatter(post)}\n${post.body}`

  fs.writeFile(`../path/to/final/content/posts/${post.slug}.md`, content, err => {
    if(err) {
      return console.log(err);

    console.log("The file was saved!");

I needed to run sudo node index.js on that as it needed to create files, but I didn’t have to touch the generated markdown files once they were in the right folder.

Once that was done, I skipped on over to Netlify and hooked it up. I needed to do some configuration before everything would work. Mainly this was down to my assets living in a theme which was in a subfolder. To let Netlify know about it, I had to create a new package.json in the root with a build command that did the following:

publish = "public"
command = "hugo --minify && npm run build"

Then the build command in my root package.json dug into the folder it needed and ran some more commands:

"scripts": {
  "build": "cd ./themes/nua && npm install && npm run production"

After that, it was smooth sailing. Limerick just won the All-Ireland senior hurling final so I’m gonna grab a beer. That makes two victories today. Cheers, agus Luimneach AbĂș!!!





I accept comments via email, and clicking "Add Comment" will open your default email client. If the thoughts of your native email client opening horrifies you, you can instead email your comment to contact@tj.ie.

Add Comment