How to move your blog from Jekyll to Next.JS

This blog was used to be statically generated with Jekyll, but not anymore!

I replaced Jekyll with Next.js, because I wanted to move away from Ruby gems . In this post, let me tell you how I did the move, so if you ever wanted to move yours, it would help you.

The plan

Here's the overview of steps that I planned for the move.

  1. Set up the Next.JS framework to compile blog posts written in markdown format
  2. Transform Jekyll blog posts from the YYYY-MM-DD-post-name.md format to post-name.mdx so Next.JS could understand it.
  3. Setting up code highlighting
  4. Set up nginx server to rewrite old URLs to new ones.

Now, let's get to the execution part of it.

1. Setting up Next.js framework to compile markdown files

By default, Next.js won't recognize mdx files. There are several tools available to make Next.js work with mdx - next-mdx-remote is one such tool. I followed this example setup from Next.js which provides a base structure to compile mdx files.

After cloning, I customized the folder structure and styles to my liking.

2. Transforming old Jekyll posts

I used to save my Jekyll blog posts in YYYY-MM-DD-post-name.md format - which won't work (or need customization) in Next.js. So, I had to move all my existing files to the post-name.mdx format.

I also had to copy the post date, which was originally part of the file name, into the front matter of my posts. For this, I used gray-matter npm package.

Here's a script that I wrote for the conversion.

const fs = require("fs")
const path = require("path");
const matter = require("gray-matter");

const POSTS_FOLDER = path.join(__dirname, "_posts");
const OUT_FOLDER = path.join(__dirname, "out");
try {
  const posts = fs.readdirSync(POSTS_FOLDER);
  for(let i=0; i<posts.length; i++) {
    const post = posts[i]
    const date = post.substr(0,10);
    const fileName = post.substr(11).replace(".md", "");
    const fileContent = fs.readFileSync(path.join(POSTS_FOLDER, post), 'utf8')

    const parsed = matter.stringify(fileContent, {
      publishedOn: date
    })

    fs.writeFileSync(path.join(OUT_FOLDER, `${fileName}.mdx`), parsed)
  }
} catch (e) {
  console.error(e)
}

Once converted, I copied all the files from my output folder to my Next.js instance.

3. Setting up code highlighting with remark-prism

I share a lot of coding examples in my blog. In Jekyll, I was using rouge highlighter for pretty printing my code. In Next.JS I have to use remark-prism for this purpose. npm install remark-prism then initialize it where you are rendering mdx to string like this

import remarkPrism from "remark-prism";
// ....
// ....
const mdxSource = await renderToString(content, {
    components,
    // Optionally pass remark/rehype plugins
    mdxOptions: {
      remarkPlugins: [remarkPrism],
      rehypePlugins: [],
    },
    scope: data,
  });

Also, I had to manually search and replace all my code block markers to the new template. For example, {% highlight javascript %} code block {% endhighlight %} to ```javascript code block ```

4. Setup nginx to rewrite URLs from old format to new format

My Jekyll posts used to have the URL of https://veerasundar.com/blog/post-name - which is unnecessarily long. I wanted to remove the year/month information from the URL. The new format will be https://veerasundar.com/blog/post-name which is much simpler. At the same time, I don't want to break all my existing URLs. So, I needed a server set up which will redirect requests to my old URLs to new ones. Here's the change I made for this

location /blog {
        rewrite ^/blog/[0-9]+/[0-9]+/(.*)/$ /blog/$1.html permanent;
        rewrite ^/blog(/?)$ /blog.html permanent;
        try_files $uri $uri.html =404;
}

That's all I had to do to move my blogging platform from Jekyll to Next.js. If you have any questions or need help in the above process, please feel free to reach out to me.