Automating some of the publishing steps for my Eleventy blog

A few weeks ago, I blogged about my complete blogging workflow. My publishing process had several tedious, repetitive, manual steps to go from the last of the writing to having the content available on my website. This is a quick writeup on the steps I've automated.

Requirements

Because I want to feel like I'm writing instead of coding during the writing process, I prefer to write in Typora instead of VS Code. Lots of people seem to have no issues with writing in VS Code directly so the first part of my process is just something quirky to my own preferences. I also do not want to have the front matter of the post just hanging out up there at the top while I'm writing for the same reason. It's distracting to me and takes me out of the right head space. YMMV.

Because of this requirement, every single post starts out as a markdown file which I will refer to as the content. Each post also has a YAML file that contains the front matter describing the content.

Staging

The first step is what I'm calling staging. This step take the content markdown file and the front matter yml file, smooshes them together, drops them into the Eleventy src directory then archives the draft files. Since Eleventy uses nodejs, it felt natural to use it to automate the staging step. I'm very new to nodejs though so if you see anything cringe worthy, please shoot me an email or message - I'm trying to get better!

const fs = require('fs');
const path = require('path');
const os = require('os');
const fm = require('front-matter');
const slugify = require('slugify');
const { DateTime } = require('luxon');
const now = DateTime.now();
const YAML = require('json-to-pretty-yaml');

// init directory vars
const homeDir = os.homedir()
const publishYearDir = now.year.toString();
const draftDir = path.join(homeDir, '/Notes/2-Writing');
const draftArchiveDir = path.join(homeDir, '/Notes/Archive', publishYearDir);
const rootPublishDir = path.join(homeDir, '/Projects/obsolete29.11ty.v4/src/posts', publishYearDir);

// get front matter file and contents
function getFrontMatter(dir) {
const yamlFile = fs.readdirSync(dir).filter(function(e){
return path.extname(e).toLowerCase() === '.yml'
});
const frontMatterFile = path.join(draftDir, yamlFile[0])
const frontMatterContent = fm(fs.readFileSync(frontMatterFile,'utf8'));
frontMatterContent.attributes.date = now.toISO()
return frontMatterContent.attributes
}
const frontMatter = getFrontMatter(draftDir);
const newFolderName = slugify(frontMatter.title, {lower:true})

// get content file and contents
const contentFile = fs.readdirSync(draftDir).filter(function(e){
return path.extname(e).toLowerCase() === '.md'
});
const fullContentFile = path.join(draftDir, contentFile[0]);
const postContent = fs.readFileSync(fullContentFile,'utf8');

// create new publish dir
const fullFolderName = path.join(rootPublishDir, newFolderName);
if (!fs.existsSync(fullFolderName)){
fs.mkdirSync(fullFolderName);
}

// write new file
const newContent = `---\n${YAML.stringify(frontMatter)}---\n${postContent}`;
const newContentFileName = path.join(fullFolderName, 'index.md');
fs.writeFileSync(newContentFileName, newContent);

// archive draft files
fs.readdir(draftDir, (err, files) => {
if (err) {
throw err;
}
files.forEach(file => {
let currentPath = path.join(draftDir, file);
let destinationDir = path.join(draftArchiveDir, newFolderName);
let destinationPath = path.join(draftArchiveDir, newFolderName, file);

if (!fs.existsSync(destinationDir)){
fs.mkdirSync(destinationDir);
}

fs.rename(currentPath, destinationPath, function (err) {
if (err) {
throw err
} else {
//console.log("Successfully moved the file!");
}
});
});
});

Package.json Node scripts

The rest of the automation is just chaining together the various commands for building the site, syncing from my computer to my website, then committing the new post to Codeberg.

Here's the relevant section of my package.json file.

{
"name": "obsolete29.11ty.v4",
"version": "1.0.0",
"description": "These are the build files for my Eleventy blog.",
"main": "index.js",
"scripts": {
"build": "npx @11ty/eleventy --incremental --quiet",
"stagePost": "node _functions/stage-post.js",
"deploy": "npm run build && npm run sync",
"sync": "rsync -rtv --delete --quiet -e 'ssh' ~/Projects/obsolete29v4/ cyberian@69.61.38.243:/var/www/obsolete29/",
"git": "git add . && git commit -m 'New blog post'",
"postgit": "git push --all",
"publishPost": "npm run stagePost && npm run deploy && npm run git"
},
}

So now my updated workflow for publishing posts looks like this:

  1. Open and populate the front-matter.yml that exists in the draft directory with my content markdown file.
  2. Open VS Codium, execute npm run publishPost.
  3. Grab a cookie to celebrate posting more great content to the internet.

Improvements

I'm pretty happy with how this turned out if I'm honest. Here are a couple more things I'd like to add to improve this process.

  1. This process currently only supports text based posts. I want to add support for images and I want to add the Eleventy short codes for images as part of that effort. I don't post many images but when I do, posting them is a tedious chore. I want to make that easier.
  2. Auto posting to socials. As part of the publishing workflow, I'd love to automatically post to Mastodon and Twitter.

OK that's it for now! Really open to suggestions and constructive feedback on any of this.

Reply via email

#blogging #obsolete29 #nodejs #eleventy