Recently I rebuilt my website because I was not happy with its SEO performance. The website used to fetch the data from the backend using javascript. That means that also the metatags, which are important for SEO, have been generated on the clientside. This basically made the metatags useless because Search Engines like Google do not care about javascript-generated metatags. I had to find a solution where these metatags can be generated on the server and then be sent directly to the client on request. I also did not want to use full Server-Side Rendering because of performance reasons. I thought it would be perfect if the server just generates static pages and then, from time to time, checks the CMS if any new pages have to be gernerated and generates them and adds them to the already existing collection of static pages. I found out that this is possible using Next.js. It's called "Incremental Static Generation".
For our blog setup we need a Next.js-Project for our frontend and a Strapi-Project for our CMS. We can create these two projects easily using the following commands.
npx create-next-app
npx create-strapi-app my-project
When creating a new Strapi-Project you have to set up a database connection. You can use every database you want, just enter the database type and the credentials. I would not recommend using SQLite because it can be difficult to transfer you data to another server in case you want to do that in the future. After creating the two projects you can set up your Strapi admin account. Just switch into the folder of the Strapi-Project and run the following command.
npm run develop
This command starts the Strapi Development Server. You can now open your webbrowser and navigate to http://localhost:1337/admin . You will be asked to enter the information for your admin account. Your next step is to create a new content type for your blogposts. Just start the content type wizard, give it a name and select the required fields. For example you can name your content type just "blogpost" and create fields for the text, the title, the date, the linktext and the image of the blogpost. You can already write a short blogpost for testing purposes. Remember to make your first blogpost public and also grant unauthorised users access to your blogposts. To do that, go to Settings, then Roles, then Public and activate all the "find" and "findone" permissions for the role "Public". When you navigate your browser to http://localhost:1337/blogposts you should already be able to see a list of blogposts in JSON-format. Next.js will later render the blog pages based on this JSON-list.
Now switch to your fresh Next.js Project. The first thing you want to do is to create a new environment variable to tell the Next.js Application where to find your Strapi Application. Create a new file in your Next.js project folder called ".env". Write the following line into this file:
REACT_APP_BACKEND_HOST=http://localhost:1337
Now we have to set up a new page which displays your blogpost. In your "pages" folder create a new folder "blog". In this new folder create a file "[post].js". In this case the "post"-page is based on a dynamic route. The page will be rendered for all blogposts provided by your Strapi CMS. To make this possible we have to tell Next.js that it should fetch data about the blogposts when building the application. We add the following to our new "[post].js" file:
export async function getStaticProps({ params }) {
const response = await fetch(process.env.REACT_APP_BACKEND_HOST + '/blogposts?link=' + params.post);
const data = await response.json();
return { props: {
title: data[0].title,
text: data[0].text
date: data[0].date,
slug: data[0].link,
image: process.env.REACT_APP_BACKEND_HOST + data[0].image.url
},
revalidate: 3600,}
}
To explain this piece of code I assume that you named you first blogpost "My first Blogpost" and you want to make it available under yourwebsite.com/blog/my-first-blogpost. To do that, you have to insert "my-first-blogpost" (the last part of the link) into the link field of your Strapi-post. Next.js will then query all the posts from your Strapi Application from time to time using the links that you specified in your posts and fetch the title, text, link, date and image. This data will be passed to your main component of this Next.js page. A very basic version of this component could look like this:
export default function Blogpost(props) {
return (
<div>
<Head>
<meta property="og:type" content="website"/>
<meta property="og:title" content={props.title}/>
<meta property="og:image" content={props.image}/>
<meta property="twitter:card" content="summary_large_image"/>
<meta property="twitter:title" content={props.title}/>
<meta property="twitter:image" content={props.image}/>
</Head>
<div style={{ height: '200px', backgroundImage: 'url(\'' + props.image + '\')' }}/>
<h1>{props.title}</h1>
<h4>{props.date}</h4>
<ReactMarkdown>{props.text}</ReactMarkdown>
</div>
)
}
This will generate metatags based on the data of the current blogpost. Don't forget to import "next/head" and "react-markdown" in your .js file. We now have to tell Next.js which routes it should use to generate blogposts. We do this by adding another function to our "[post].js" file.
export async function getStaticPaths() {
const res = await fetch(process.env.REACT_APP_BACKEND_HOST + '/blogposts')
const posts = await res.json()
const paths = posts.map((post) => ({
params: { post: post.link },
}))
return { paths, fallback: true }
}
This function queries all available links to posts from your Strapi backend and passes them to the getStaticProps function for every post that has to be rendered. We are basically done now, we only need a page which displays an overview of all available blogposts on your blog. In your blog folder you have to create a file "index.js" and add a function getStaticProps() which fetches information of all available posts and passes the information to the page component. This function could look like this:
export async function getStaticProps() {
const response = await fetch(process.env.REACT_APP_BACKEND_HOST + '/blogposts');
const data = await response1.json();
let posts = []
data.map((item, index) => posts.push({
title: item.title,
link: item.link,
date: item.date,
image: process.env.REACT_APP_BACKEND_HOST + item.image.url
}))
return { props: {
posts: posts
},
revalidate: 3600,
}
}
In you page component you can access the array of posts via props.posts and render them in any way you want.
You are now ready to deploy your new blog to your server. Just move the files to the server (without node_modules or it will take forever via SFTP). On the server build the strapi project by switching into its folder, then run the follwoing command:
NODE_ENV=production npm run build
The Strapi backend can then be started using the following command:
NODE_ENV=production npm start
Build the Next.js project by switching into its folder, then run the following command to build the project:
npm run build
Then start the Next.js Application using this command:
npm start
Thats it. Dont forget to make sure that the right ports are open on your server and that you inserted the right URL of your backend into the .env file. For example this website is hosted on huelser.me and the backend is hosted backend.huelser.me. How domains can be mapped to ports depends on which server you are using
Photo by Amelia Bartlett on Unsplash