paint-brush
Build a Guestbook App Using Next.js ISR Feature and Webhooksby@tomhacohen
1,017 reads
1,017 reads

Build a Guestbook App Using Next.js ISR Feature and Webhooks

by Tom HacohenSeptember 12th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

On-demand Incremental Static Regeneration (ISR) enables developers and content editors to use static-generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages. Next.js 12.1 (released today) has introduced on-demand ISR which gives developers the flexibility to manually purge the Next.js cache for a page on-Demand. ISR is already great and is used by many companies to drastically improve their bulid times while retaining incredible performance.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Build a Guestbook App Using Next.js ISR Feature and Webhooks
Tom Hacohen HackerNoon profile picture

Today Vercel launched Next.js 12.1 and with it their highly requested feature — on-demand Incremental Static Regeneration (ISR)! Many thanks to Vercel for sharing a preview of ISR with us, and featuring us in their announcement post!


With on-demand ISR you can now build real-time static websites. The websites are dynamic and they change in real time, though they are statically generated in the background. So you get both ultra-fast page loads and global distribution.


How does it work, and how does it relate to Six? Read on for more information and a fun example.


Special thanks to our awesome customer Clerk, for building the examples used in this post! Clerk helps Next.js developers add sign-up, sign-in, and user profile management to their applications in minutes.

What is Svix?

Svix is an enterprise-ready webhooks service.


Sending webhooks requires a lot of engineering time, resources, and ongoing maintenance. Svix lets you build a state-of-the-art webhooks solution in minutes so you can focus on your business.


We power the webhooks for many amazing companies, and we've also recently open-sourced our webhooks dispatcher.

What is Incremental Static Regeneration (ISR)?

Next.js allows you to create or update static pages after you've built your site. Incremental Static Regeneration (ISR) enables developers and content editors to use static generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.


Static pages can be generated at runtime (on-demand) instead of at build-time with ISR. Using analytics, A/B testing, or other metrics, you are equipped with the flexibility to make your trade-off on build times.


Does the above look familiar? It's because it's from the wonderful Vercel docs. Please check them out for more information.

What is on-demand ISR?

ISR is already great and is used by many companies to drastically improve their build times while retaining incredible performance. However, the current interval-based re-validations have proved insufficient for some use cases. Next.js 12.1 (released today) has introduced on-demand ISR which gives developers the flexibility to manually purge the Next.js cache for a page on-demand.


It's exciting for a variety of reasons and uses cases. One thing that it enables that is especially cool is building real dynamic websites with statically generated website performance.

You no longer need dynamic routes to have dynamic pages. You can now, in real-time, trigger page rebuilds so that they show the most up-to-date data as it changes.

Building the real-time guestbook

Webhooks are one of the best ways to trigger on-demand ISRs, so using Svix with on-demand ISR is a natural fit.


We are going to build a real-time guestbook. Visitors of this website will be able to signup and create their user profile. The website will then list all of the recently signed-up users (in real-time!). Users will also have their profile page that they can edit and share with others.

I know it sounds like a lot because it is. Though using Vercel (deployment), Next.js (On-Demand ISR), Svix (webhooks), and one of our customers, Clerk (user profile management and authentication), it's going to be a breeze.


You can try out the live example and continue reading about how it was built.


The first step would be to build our website's main UI. We would need a nice description explaining what this website does, a signup button, and a list of users.


Main page screenshot


This is what the code to fetch the list of customers looks like:

// pages/index.js

import Head from 'next/head'
import Image from 'next/image'
import { SignUpButton } from '@clerk/nextjs'
import clerk from '@clerk/clerk-sdk-node'

export async function getStaticProps(context) {
  const users = (
    await clerk.users.getUserList({
      orderBy: '-created_at',
      limit: 10,
    })
  ).map((u) => ({
    id: u.id,
    firstName: u.firstName,
    lastName: u.lastName,
    profileImageUrl: u.profileImageUrl,
    createdAt: u.createdAt,
  }))
  return {
    props: { users }, // will be passed to the page component as props
  }
}

export default function Home({ users }) {
  // ...
}

Though remember, we haven't added ISR yet, so the list of customers was generated at build time and will remain static until the next build. Let's make it dynamic!


The next step would be to implement the new on-demand trigger every time a user signs up. We'll create an API route in our Next.js app to add a webhook receiver:

// pages/api/revalidate.js

import { Webhook } from 'svix'
import { buffer } from 'micro'

export const config = {
  api: {
    bodyParser: false,
  },
}

export default async function handler(req, res) {
  // Check for secret to confirm this is a valid request
  const payload = (await buffer(req)).toString()
  const headers = req.headers

  const wh = new Webhook(process.env.SVIX_SECRET)
  let msg
  try {
    msg = wh.verify(payload, headers)
  } catch (err) {
    res.status(500).json({ error: 'Webhook verification failed' })
  }

  try {
    // Rebuild the homepage to update the recent sign ups
    await res.unstable_revalidate('/')
    return res.json({ revalidated: true })
  } catch (err) {
    // If there was an error, Next.js will continue
    // to show the last successfully generated page
    res.status(500).json({ error: 'Revalidation failed' })
  }
}

In the code snippet above, we are using the Svix JavaScript library to verify that the webhook was indeed sent from Svix and wasn't maliciously triggered by anyone else.


Now we need to trigger it so that the ISR regenerates the page. To do that we'll head over to the Clerk dashboard, and click on the Svix webhooks configuration to add our webhook endpoint.


We'll want to set the URL to https://svix-vercel-revalidation.clerk.app/api/revalidate and listen to the user.created and user.deleted event types.


Adding webhook example


We now need to set the SVIX_SECRET environment variable to the secret we get from Svix, and that's it! We've built a real-time statically generated website using Vercel, Next.js, Svix, and Clerk.

Let's recap how this whole thing works together. We first build a Next.js application and then deploy it on Vercel. We then go to the Svix section on the Clerk dashboard and add our webhook. With the webhook set, every user creation or deletion on Clerk will trigger a webhook to Vercel, which will in turn trigger the ISR regeneration and rebuild the page. It's that simple!


In case you missed it above, you can try it out here: https://svix-vercel-revalidation.clerk.app/, and view the source code on Github.

Closing words

We had a lot of fun building this with Vercel and Clerk, and it shows how much you can achieve (and with what performance!) by combining a few cool services.

If you want your customers to be able to build workflows and automation on top of your service, like the one you saw in this post, you should give Svix a try.


This is it for this update, but make sure to follow us on Twitter, GitHub, or RSS for the latest updates for the Svix webhook service, or join the discussion on our community Slack.


Also Published here