Published on

Baby Steps with Next.js for JAMstack

Authors

This is going to a different type of post than I usually do. I want to share my learning experience getting started with Next.js. My hope is that some of this might be useful for you those of you interested in learning Next.js, but also to hopefully learn from those of you who already know Next.js.

So up front, let me be frank. I am a total React noob. Somehow, despite its ubiquity in today's frontend development ecosystem, I've managed to avoid it. Partly this was because I was never in a position to have to use it and partly this was because I found the React ecosystem a bit overwhelming and intimidating.

However, I've been really interested in checking out Next.js. From what I'd read and seen, it seemed to make React approachable. And, even more interesting for me, it even allows for statically generating assets, making it an option for JAMstack development.

Where to Learn Next.js?

Next.js has a nicely done learn guide that tries to help motivate you by awarding your points for completing tasks and answering quiz questions. It does a pretty nice job of covering the basics. That being said, I didn't feel ready to jump in and build something at this point. I was looking for something that would dive a little deeper - preferably a video training of some sort.

After doing some research I stumbled on this training by Remy Sharp. It appears to be a number of versions behind on Next.js, so some aspects of it seem to be outdated, but most of the basics it covers in the first modules are still relevant. Overall, it gave me what I was looking for even if it could use some updating.

Creating a Learning Project

The next step was to actually start trying to build something with Next.js. Since my goal was to explore it's usage for JAMstack, I decided to look into how to rebuild my current blog that was built using Jekyll. While it isn't a complex site, there's enough there to force me to learn a lot about Next.js.

The goal was to recreate the blog, including generating content assets that are currently written in Markdown with YAML front Matter. Next.js doesn't appear to natively support this at this time. There is an official MDX loader plugin but my posts were not written using MDX and I was not looking to convert all of them.

Thankfully, Kendall Strautman wrote a great post on building a Markdown blog with Next.js and an associated sample project repository. This provided enough detail to get me going.

I have some of the basics working in my repo including a dynamic route [slug].js that handles any post URL and loads the appropriate content.

import * as React from 'react'
import matter from "gray-matter";
import ReactMarkdown from "react-markdown";

import Layout from '../../components/layout'

export default function BlogTemplate(props) {
    function reformatDate(fullDate) {
        const date = new Date(fullDate)
        return date.toDateString().slice(4);
    }
    const markdownBody = props.content
    const frontmatter = props.data
    return (
        <Layout config={props.config}>
            <div>
            <h1>{frontmatter.title}</h1>
            <h2>
            {frontmatter.description}
            </h2>
            <h3>{reformatDate(frontmatter.date)}</h3>
            </div>
            <div>
            <ReactMarkdown source={markdownBody} />
            </div>
        </Layout>
    )
}

BlogTemplate.getInitialProps = async function(ctx) {
    const { slug } = ctx.query
    const content = await import(`../../posts/${slug}.md`)
    const config = await import(`../../data/config.json`)
    const data = matter(content.default);
    return {
        ...data,config
    }
}

One issue right now is that the slug is based upon the file name, which Jekyll requires formatting with the date string. So instead of using /blog/joining-stackbit, I currently need to use /blog/2019-10-09-joining-stackbit. Whether this is a problem fixable by code or simply by renaming all the files, I do not know yet.

Passing Down Config Properties

Next.js has a special method called getInitialProps(), which is a useful way to load any needed data the page needs. One of the things I wanted to do was to load site-wide configuration data similar to how it is done with Jekyll. What I quickly learned was that this method isn't available in components (at least not without some tweaking), just regular pages.

In the end, I opted to load the data in the page and then pass it down to the layout. This ends up being a bit redundant rather than automatic. Maybe I'm doing this wrong but do I need to load this on each page or is there a way to centralize loading it just once? This way I then need to pass it down from the layout component to each component that makes up the layout. I am not sure if this is considered a best-practice or antipattern for React.

Home.getInitialProps = async function() {
  const configData = await import(`../data/config.json`)
  return {
    ...configData
  }
}
<Layout config={props}>
</Layout>

I am not sharing this as how it should be done...more as "Am I doing this right?"

Next Steps

That's my status right now. I can load posts, but the layout is awful. Next steps will be:

  • Improving the layout (adding a design)
  • Handling sub-pages or data (I have content generated from YAML files in my current blog)
  • Figure out how to handle categories that are in the front matter and allow for filtering as I do here in my current blog
  • Reimplement the site search that is currently built with Lunr
  • Finally, I will need to configure the whole thing to statically generate the output files to deploy to Netlify.

I welcome any Next.js advice! 🙏🏻