Juan Olvera

Rebuilding my blog with Next.js

In Progress

I use my website for hacking with new technologies more than writing content. This time Im rebuilding it using Next.js and if youre reading this, I already deployed the first version.

Why Next.js

With the rise of React and the SSR frameworks, e.g. Gatsby and Next.js, I saw a lot of good looking, fast blogs built with Gatsby. You probably have already seen Dans. Of course I went and tried to setup my own, but the thing I didn't like was that Gatsby blog-starter uses GraphQL, which is awesome, but I don't think I need that for a simple blog.

So with the bad habit I have of wanting to build my own version of everything, I started to investigate how to build my blog with Next.js.

How

I got familiar with Next.js in the past few months by contributing an example and other small changes. Im also currently building two products with it, so I felt confident that I could build something decent.

Checklist

I started with an empty project created with create-next-app and from there I made a list of the features I needed.

  1. Create an object of posts from a list of MDX files
  2. Add syntax highlighting
  3. Add an RSS feed
  4. Add pagination

For a Next.js project, all these things were new for me and I had no idea how to implement them. So, I went to investigate how other people are doing it.

Guillermo Rauch (@rauchg) told me that Max Stoibers site (@mxstbr) was one of his favorite blogs built with Next.js out there, so I looked at his GitHub repo.

80% of the work was already done in Maxs repository and I was fortunate to chat with him about it too. Most of the credit for the work goes to him, his implementation is pretty clever and helped me a lot.

1. An Object of blog posts

To solve the first issue, Max used babel-plugin-preval/macro. This package lets you run Node code dynamically in a client context and export the results.

Using the file system module we get all the files from given folder (e.g., posts/), extract the meta data, content, path and return an Object with all the info we need. See Maxs implementation.

With this we can import the list of blog posts as import blogposts from "../../data/blog-posts"; and use it in a blog.js page. See Maxs implementation and mine.

For a simpler example we could do something like this.

import blogposts from "../posts/index";

const Blog = () => (
  <ul>
    {blogposts.map((post, index) => (
      <li key={index}>
        <a href={post.path}>{post.title}</a>
        <time>{post.publishedAt}</time>

        {post.summary}
      </li>
    ))}
  </ul>
);

export default Blog;

2. Syntax highlighting

The second issue was trickier. Basic syntax highlighting worked with rehype-prism, but one key feature was missing. The ability to highlight a line of code, e.g.:

Snippet of code from Dan Abramov’s blog

This was probably the hardest part of the process (for me). To implement this I went to a rabbit hole of learning about unified.js and how syntax trees work. I had to understand how the Gatsby team and contributors implemented their own and how to plug it into the MDX plugin interface.

I stole code got inspiration from these packages:

I won't go in detail, but I integrated code from those three packages to get syntax highlighting working along with the line highlighting feature. There are other features that are missing but this will do it for now. See the current implementation, I'll probably make a pull request to rehype-prism to add this functionality or publish a separate module.

3. RSS feed

This was easy. I followed Maxs lead of using the JSON feed spec and reformatting the blog post Object into a JSON RSS feed.

I still haven't figure out how to create the JSON file on build time, so for now I'm running the node script before committing changes to generate the feed and routing it as a static file.

4. Pagination

This was easy, too. I used the pagination library with the blog posts Objects length and other options as input.

Deployment

After all this I got the project into a good-enough working blog using Next.js, at this point I was really excited to have it deployed and that Saturday night I decided to launch it using Now 2.0.

Development environment

One of the benefits of using Next.js with Now 2.0 is the new now dev command. You get to see exactly what you will get in production. It uses the same now.json configuration file and pretty much everything else works the same way.

All the work felt easier than it should.

Conclusion

The website feels really fast. The Lighthouse audit results are amazing. The easiness of adding content feels as if you were dealing with a CMS, except theres no login.

The SSR and pre-fetching features Next.js provides makes the site feel very smooth, fast and responsive.

So far I'm very happy with the experience of developing with Next.js and Now and the results speak for themselves. I will submit a pull request to the Next.js repository to add the blog as an example, and I hope somebody will find this work useful as I found Maxs.

Also published in:

Webmentions

  • Tweets with a link to this post appear as Webmentions.

    Leave a comment