Embrace the Jamstack: Building Lightning-Fast Static Sites with Next.js and Vercel

If you're a web developer, you're probably familiar with the traditional method of building websites: create server-side scripts that dynamically generate HTML pages on the fly, to be served up to the user's browser when they request a page. This approach has been the standard for decades. However, it has its drawbacks, such as poor performance, limited scalability, and maintenance headaches.

But there's a better way: the Jamstack architecture. Jamstack stands for JavaScript, APIs, and Markup. It's a modern approach to building websites that delivers faster load times, improved security, and seamless scalability. In this article, we'll explore the power of the Jamstack and how you can harness its power to build lightning-fast static sites using Next.js and Vercel.

What is the Jamstack Architecture?

The Jamstack is a dynamic approach to building websites that uses pre-built markup, JavaScript, and APIs. The idea is that all the heavy lifting happens during the site's build process, generating static HTML files that can be served up directly to the user's browser without needing to run any server-side code. This approach has several advantages:

  • Improved performance: because the site is fully loaded in the user's browser, page load times are incredibly fast. They don't need to wait for server-side scripts to run in order to see the content they're looking for.
  • Better scalability: because the site is static, it can be served up to millions of users simultaneously without any performance issues. No more worrying about server capacity or expensive hosting infrastructure.
  • Improved security: static sites are inherently more secure than dynamic sites because there's no scripting being run on the server. This reduces the risk of hacks and exploits.

Creating a Jamstack Site with Next.js and Vercel

Now that we've covered the benefits of the Jamstack, let's dive into building a static site using Next.js and Vercel. Next.js is a powerful React-based framework that simplifies the process of building dynamic and static websites. Vercel is a cloud-based serverless deployment platform that simplifies deploying and scaling your Next.js app.

Prerequisites

In order to follow along with this tutorial, you'll need the following:

  • Node.js installed on your local machine.
  • A GitHub account, with a new repository for this project.
  • A Vercel account.

Step 1: Setting up the Project

First, we need to set up a new Next.js project. In your terminal, run the following command:

$ npx create-next-app my-jamstack-site

This creates a new Next.js project using the default template. Next, cd into the project directory:

$ cd my-jamstack-site

And let's add some additional dependencies to our project:

$ npm install gray-matter remark remark-html

We're installing gray-matter, which allows us to parse markdown files and extract metadata, remark, which is a markdown processor, and remark-html, which is a plugin that allows us to convert Markdown to HTML.

Step 2: Creating the Content

Now that we have our project set up, let's create some content to display on our site. Create a new directory in the root of your project called "content". Inside the content directory, create a new file called "hello-world.md". This file should contain the following:

---
title: "Hello, World!"
date: "2022-01-01"
---

# Welcome to my Jamstack site!

This site was built using Next.js and Vercel. Thanks for checking it out!

This is a very simple Markdown document that contains some metadata at the top (the title of the page and its publication date) and some content below. Feel free to change the content to whatever you like.

Step 3: Creating the Page Template

Next, let's create a template for our post pages. Create a new file in the root of your project called "Post.js". This file should contain the following:

import Head from "next/head";
import matter from "gray-matter";
import remark from "remark";
import html from "remark-html";

export async function getStaticProps({ params }) {
  const post = await import(\`../content/\${params.slug}.md\`);
  const { data, content } = matter(post.default);

  const processedContent = await remark().use(html).process(content);
  const contentHtml = processedContent.toString();

  return {
    props: {
      title: data.title,
      date: data.date,
      contentHtml,
    },
  };
}

export async function getStaticPaths() {
  const posts = (context => {
    const keys = context.keys()
    const values = keys.map(context)
    const data = keys.map((key, index) => {
      let slug = key.replace(/^.*[\\\/]/, '').slice(0, -3)
      const value = values[index]
      const document = matter(value.default)
      return {
        frontmatter: document.data,
        slug,
      }
    })
    return data
  })(require.context('../content', true, /\.md$/))

  const paths = posts.map(post => ({
    params: { slug: post.slug },
  }));

  return { paths, fallback: false };
}

export default function Post({ title, date, contentHtml }) {
  return (
    <article>
      <Head>
        <title>\${title}</title>
      </Head>
      <h1>\${title}</h1>
      <p>\${date}</p>
      <div dangerouslySetInnerHTML={{ __html: contentHtml }} />
    </article>
  );
}

Don't worry if this code seems overwhelming at first glance. Let's break it down:

  • We're importing a few packages: Head from Next.js, matter from gray-matter, remark, and html from remark-html.
  • We've defined two functions: getStaticProps and getStaticPaths. getStaticProps fetches the data for a specific post, given its slug. getStaticPaths generates a list of all the post slugs.
  • The Post component accepts three props: title, date, and contentHtml. We're using dangerouslySetInnerHTML to render the post content as HTML.

Now we need to create a template component that uses the Post component to display our content. Create a new file in the root of your project called "PostTemplate.js". This file should contain the following:

import Head from "next/head";
import Link from "next/link";

export default function PostTemplate({ posts }) {
  return (
    <>
      <Head>
        <title>My Jamstack Site</title>
      </Head>
      <nav>
        <ul>
          <li>
            <Link href="/" passHref>
              <a>Home</a>
            </Link>
          </li>
        </ul>
      </nav>
      <main>
        <h1>My Blog</h1>
        <ul>
          {posts.map(post => (
            <li key={post.slug}>
              <Link href={`/post/\${post.slug}`} passHref>
                <a>\{post.frontmatter.title\}</a>
              </Link>
            </li>
          ))}
        </ul>
      </main>
    </>
  );
}

The PostTemplate component is responsible for rendering a list of all the posts on our site. Similar to the "Post.js" file, don't worry if this code seems overly complicated at first. Let's break down what we're doing:

  • We're importing Head and Link from Next.js.
  • Our component accepts one prop, posts, which is an array of all the posts on our site. We're looping through this array and rendering links to each post.

Step 4: Generating the Static Site

Now that we have our content and template components set up, we need to generate our static site. To do this, we'll use the "next export" command. Run the following command in your terminal:

$ npm run build

This will create a new directory in your project called "out". This directory contains our generated static site.

Step 5: Deploying the Site to Vercel

Finally, we need to deploy our site to Vercel. The easiest way to do this is to link your GitHub repository with your Vercel account. Once you've done that, Vercel will automatically build and deploy your site every time you push changes to your repository.

In order to link your Vercel account with your GitHub repository, follow these steps:

  1. Log into your Vercel account and click the "New Project" button.
  2. Select "Import Git Repository".
  3. Select your GitHub account.
  4. Select your repository and click "Import".
  5. Vercel will automatically detect that your app is a Next.js app and configure the build settings for you. It will also display a live preview of your app so you can check that everything is working correctly.
  6. Click "Deploy" to deploy your site to production.

And that's it! Your site is now deployed and ready to be accessed by the world.

Conclusion

The Jamstack architecture is a powerful way to build highly performant and scalable websites. By pre-building your sites, you can achieve near-instantaneous load times and seamless scalability without any additional server-side infrastructure. Next.js and Vercel make it easy to build and deploy Jamstack sites, so start exploring the possibilities and building amazing experiences for your users.