Svix Blog
Published on

Building a Guestbook Using Vercel's On-Demand ISR and Svix

Authors

Cover image

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 on 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 Svix? 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 application in minutes.

What is Svix?

Svix is the 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 own 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 use-cases. One thing that it enables that is especially cool is building real dynamic websites with statically generated websites performance.

You no longer need dynamic routes in order 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 own 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 for 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 the list of users.

Main page screenshot

This is how 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. In order 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 webhooks 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 it, 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 really shows how much you can achieve (and with what performance!) by combining a few cool services together.

If you want your customers to be able to build workflows and automations 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.