New Blog Post Utility

I wrote a script that generates the boilerplate for a new blog post

Inspired by Josh Comeau's create-new-component utility, I wrote a script that creates the boilerplate folders and files for a new blog post.

A Directory Per Blog Post

My blog posts are written in MDX and they're stored locally in my Next.js app.

I've orginized my files so that each blog post lives in its own folder.

Each folder contains an MDX file and any images that are used in the blog post. An index file exports the MDX file so that when someone visits the post's URL, the content in the MDX file is rendered.

└── writing/
    └── blog-post-slug/
        ├── blog-post-slug.mdx
        ├── index.js
        ├── image1.jpg
        └── imageN.jpg

This Setup Allows Me to Colocate Images

I like this setup because I can colocate images with the blog post content, which makes it easier to find and update images if I need to.

Also, by colocating images, I can statically import images in the MDX file and that provides some advantages when using Next's Image component.

Next.js will automatically determine the width and height of your image based on the imported file. These values are used to prevent Cumulative Layout Shift while your image is loading.

Automating the Boilerplate

The problem with this setup is that it's a pain to set up manually. I have to create the folder, the mdx file, and the index file, and I have to make sure that everything is named correctly and that slug matches in several places.

So I wrote a utility to do this for me.


The utility is a node script that you can run from the command line. It takes one argument, the slug of the blog post.

node create-blog-post blog-post-slug

Right now the folder path is hard-coded for this project, but I'd like to make it more flexible in the future.

Pages vs. App Router

I'm currently using the Pages router setup in Next.js but this folder structure should still work for the App router. I'd have to swap out the index file in each blog post folder with a pages.js file.

import Post from './blog-post-slug.mdx'
export default function Page() {
  return <Post />
More Writing
  1. How to Design and Implemenent Theming

    Theming in design systems

  2. Why Implement Theming?

    Theming in design systems

  3. 2023 Year In Review

    Reflecting on what happened in 2023

  4. How I’ve Been Using AI

    A look back at how I used AI in 2023