This is a quick recipe for making a scaffolding script for my Astro blog.

The goal is to be able to scaffold a new file content/posts/my-cool-post.mdx with pre-populated frontmatter using a command like:

npm run post:create "My cool post!"

Working backwards, let’s create the post:create script in our package.json:

"scripts": {
  // ...
  "post:create": "node scripts/create.js"
},

Then, put the following in scripts/create.js. Remember to update the author variable:

import { access, writeFile, constants } from 'node:fs/promises';

// Update me!
const author = 'FIXME';

// Update me if you want to!
// postDir is relative to the project root
const postDir = 'src/content/posts';
const postExt = '.mdx';

/**
 * Creates a new post in the posts content directory.
 */
async function create() {
  const title = process.argv[2];
  if (!title) {
    console.error('Please provide a title for the post');
    process.exit(1);
  }

  // Strip time component from the date
  const date = new Date().toISOString().split('T')[0];

  // Slug-ify the title
  const slug = title.toLowerCase().replace(/[\W-]+/g, '-');

  // file path is relative to this file's import URL
  const filepath = new URL(
    `../${postDir}/${slug}${postExt}`,
    import.meta.url
  );

  const content = `---
title: "${title}"
author: "${author}"
date: ${date}
tags: ["FIXME"]
draft: true
summary: |
  FIXME
---
`;
  try {
    await access(filepath, constants.R_OK);
    console.log('File already exists', filepath.href);
  } catch (_) {
    await writeFile(filepath, content);
    console.log('File created', filepath.href);
  }
}

create()
.catch((err) => console.error('error', err));