While migrating my blog from Hugo to Next.js, I encountered a problem. In Hugo, I could easily keep the images in the same folder as the markdown file, but Next.js did not offer this feature. Relocating all the images manually seemed like a tedious task, so I devised a plan to automate it during the build process.

Step 1: Gathering Images at Build Time

To begin, I needed to create a folder within /public/images for each blog post and move the corresponding images into them. To achieve this, I created a postbuild.mjs file with the following code snippet:

import fs from 'fs'
import path from 'path'
import fsExtra from 'fs-extra'

const source = './content/posts'
const destination = './public/images'

const posts = fs.readdirSync(source)

fsExtra.emptyDirSync(destination)

fs.mkdir(destination, () => {
  posts.map((slug) => {
    if (slug === '.DS_Store') return

    fs.mkdir(`${destination}/${slug}`, () => {
      fs.readdirSync(`${source}/${slug}`)
        .filter((item) =>
          ['.png', '.jpg', '.jpeg', '.gif'].includes(path.extname(item))
        )
        .map((item) => {
          fs.copyFile(
            `${source}/${slug}/${item}`,
            `${destination}/${slug}/${item.replace(/ /g, '-')}`,
            () => {
              console.log(`${destination}/${slug}/${item}`)
            }
          )
        })
    })
  })
})

This code reads each blog post directory, filters out the image files, creates the corresponding folder in /public/images, and copies the images into their respective folders.

Step 2: Updating the Package.json File

To ensure the postbuild.mjs script is executed after the Next.js build process, include the following postbuild entry in your package.json file’s scripts section:

{
  ...
  "scripts": {
    "build": "next build",
    "postbuild": "node ./postbuild.mjs",
    "dev": "next dev",
    "start": "next start",
    ...
  }
}

You can also create a prebuild entry that runs before the build process, using the same technique. Note that this feature is not unique to Next.js; it is a broader npm feature. Refer to the npm documentation for more information.

By following these steps, you can efficiently manage your images and streamline your workflow when using Next.js.