Strapi
Published in

Strapi

How to Create an SSG (Static Site Generation) Application with Strapi Webhooks and NextJs

Learn the advantages of each rendering method provided by Next.js. Then build an SSG (Static Site Generation) blog application using Strapi, Next.js, and webhooks.

Prerequisites

To proceed, you must have a basic understanding of the following:

  • Basic understanding of Next.js.
  • Basic understanding of Strapi
  • Git and GitHub

Next.Js Rendering Methods

Here, we’ll explore the different rendering methods that Next.js provides as earlier mentioned.

Client-Side Rendering

This is the usual kind of data fetching using useEffect hooks; data is mainly fetched by API calls on the client side. The client will receive this code, execute the request and build the page.

Server-Side Rendering

Server-side rendering is ideal for creating pages with fast loading speed. It is also beneficial for page SEO. In server-side rendering, the server generates HTML and sends the entire page in the response to the client request.

Static Site Generation

Static site generation can be very useful if a website does not rely on any external data and only serves static pages that rarely change. SSG describes the process of building websites that render at build time. The output is an HTML file, assets such as JavaScript and CSS, and a few other static files.

  • getStaticPaths: This function generates a list of pages that will be pre-rendered at build time. If we want to create dynamic routes, we can use getStaticPaths. Next.js will dynamically pre-render all the paths specified by getStaticPaths.
  • A dynamic page template

Setting Up Strapi

Strapi is the leading open-source, customizable, headless content management system (CMS) based on Node.js. Strapi has a nice user interface for building our APIs.

Scaffolding the Strapi Backend

In the terminal, create a new folder blog. This is where our application will live:

mkdir blog
cd blog
npx create-strapi-app@latest <app-name> --quickstart
# or
yarn create strapi-app <app-name> --quickstart
blog {
title
description
draft
imageUrl
}

Creating a Blog Collection Type

On the admin panel, in the sidebar, click the Content-Type Builder button. This will take us to the Content-Type Builder plugin page. Click on + Create new collection type. This will pop up a Create a collection type modal.

strapi blog
select field type
strapi collection field
  • field Name description; type Text Long text
  • field Name draft; type Rich text
  • field Name imageUrl; type Text Short text
saving strapi collection field

Seeding the Database

Next, we will add content to our database. Click on Content Manager on the sidebar. Under COLLECTION TYPES, select blog.

creating strapi blog post
creating strapi blog post

Open Access to Blogpost Entries

By default, only authenticated users can access the endpoints for the new blog entries created above. Let’s make the endpoints available to the public. To do this:

  • In the USERS & PERMISSIONS PLUGIN section, click on Roles
  • On the Roles page, click on Public
strapi roles

How to Create a Next.js SSG Application

Getting started with Next.js is as simple as running a single command in the terminal. Paste and Run the following code in a new terminal window in the blog folder directory:

npx create-next-app blog-ssg
npm install front-matter marked
  • marked: This dependency is used for parsing markdown into HTML string
npm run dev
NEXT_PUBLIC_STRAPI_URL="http://localhost:1337/api"
DOMAIN="i.imgur.com"
.container, .post {
width: 100%;
min-height: 100vh;
margin: 0 auto;
padding: 40px 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container h1, .post h1 {
font-size: 2em;
}
.card {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
padding: 40px 0;
}
.flexing {
width: 30%;
box-sizing: content-box;
background: #f8f6f8;
margin: 1%;
padding: 30px;
border-radius: 8px;
}
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
domains: [`${process.env.DOMAIN}`]
},
};

module.exports = nextConfig
import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import styles from "../styles/Home.module.css";

export const getStaticProps = async () => {
const resulting = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/blogs`);
const result = await resulting.json();
return {
props: {
result: result.data,
},
};
};

export default function Home({ images, result }) {
return (
<>
<Head>
<title>thisBlog</title>
<meta title="description" content="This is an example of our blog" />
</Head>
<div className={styles.container}>
<h1>Blog Post Links:</h1>
<div className={styles.card}>
{result.map(result => {
return (
<div className={styles.flexing} key={result.id}>
<Link href={`/blog/${result.id}`}>
<Image
src={`${result.attributes.imageUrl}`}
alt="blog-post"
priority={true}
className="rounded-full"
width={300}
height={300}
/>
<h2>{result.attributes.title}</h2>
<div>
<p>{result.attributes.description}</p>
</div>
</Link>
</div>
);
})}
</div>
</div>
</>
);
}
  • Used the function getStaticProps. This is a function introduced by Next.js that can be used to generate static sites. The getStaticProps function is used to fetch the contents of our blog posts and pass them as props to the Home component.
  • Destructured and utilized the props returned by the getStaticProps functionNext in the home component.
  • Used Next.js Head to set the page's metadata.
  • And Link is a special component from Next.js that we can use to navigate pages.
blog homepage
import React from "react";
import fm from "front-matter";
import Head from "next/head";
import { marked } from "marked";
import Image from "next/image";
import styles from "../../styles/Home.module.css";

export const getStaticPaths = async () => {
let result = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/blogs`);
result = await result.json()
return {
paths: result.data.map(result => ({
params: { id: result.id.toString() },
})),
fallback: false,
};
};

export const getStaticProps = async ({ params }) => {
const res = await fetch(
`${process.env.NEXT_PUBLIC_STRAPI_URL}/blogs/${params.id}`
);
const markdownWithMeta = await res.json();
const parsedMarkdown = fm(markdownWithMeta.data.attributes.draft);
const htmlString = marked(parsedMarkdown.body);
const image = markdownWithMeta.data.attributes.imageUrl;
return {
props: {
image,
htmlString,
data: parsedMarkdown.attributes,
},
};
};

export default function Post({ image, htmlString, data }) {
return (
<>
<Head>
<title>{data.title}</title>
<meta name="description" content={data.description} />
</Head>
<div className={styles.post}>
<Image
src={`${image}`}
alt="blog-post"
priority={true}
className="rounded-full"
width={600}
height={400}
/>
<div dangerouslySetInnerHTML={{ __html: htmlString }} />
</div>
</>
);
}
  • To set our metadata dynamically, we also imported the front-matter dependency.
  • Additionally, the mark dependency transforms our draft’s markdown into htmlString
  • We are using the Next.js getStaticPath this function will return an object with a path property which is an array, and the fallback is set to false, this means any paths not returned by getStaticPaths will result in a 404 page.
  • And in the getStaticProps function we are returning our image htmlString and parsedMarkdown.
  • Where the parsedMarkdown contains our pages metadata, and the htmlString Is our converted metadata. All are sent in a props object to be passed to the Post component.
  • The dangerouslySetInnerHTML prop is offered as React's replacement for the DOM element's innerHTML property.
Blog Post Image

Deploying Strapi and Next.js Application

To use Strapi webhooks successfully, we have to deploy our applications. Strapi provides us with a number of options to deploy our CMS backend. Deploy your Strapi application to your preferred host provider.

Repo Image
vercel
vercel
  • DOMAIN: This is the domain name of our blog post image provider.
setting env variable

Strapi WebHook Setup

Finally, a webhook would operate as the listener to simply alert and update our deployed static generated application whenever changes are made to the blog data. In essence, it is a solution that allows apps to communicate with one another, notifying and tracking events between them.

  • We can give the hook any name, but in this case, we are calling it application hook and stating main, this means when the hook is activated, the application’s main branch will be rebuilt and redeployed. To create our hook URL, click the Create Hook button.
webhook
webhook
webhook in action

Conclusion

Webhooks are a simple way for your applications to communicate with one another and receive notifications when a new event occurs. I hope you enjoyed reading this article. For more information on how to use webhooks in your Strapi application you can check here:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store