How to create a SEO-friendly website using NextJS & Notion API ?

Notion API

NextJS

July 28, 2022

How to create a SEO-friendly website using NextJS & Notion API ?

Today, we will see how to create your own SEO-friendly static website which can be a blog, an ecommerce, a portfolio or whatever you want it to become !

Source code here : Github Repo (OpenSource).

You can fork it, copy and do anything you want with this code, it's free !

Setting up the project

Create a Notion integration

Follow this link: your integrations and create a new internal integration.

  • Give it a name
  • Select the right workspace to link
  • Give it the ability to read your content

Then save it.

Build your Notion database

Create a page in your Notion workspace, containing a Database. You can put the properties you want and the lines you want, but never let an empty line ! For example, there is the database used in this article (you can duplicate it):

https://www.notion.so/f394d3f878ce4c6b88412da5391e4603

In a future step, you will need your database ID. To find it, click the Share button on your own database and get the ID between the / and the ? The ID of the example database is f394d3f878ce4c6b88412da5391e4603 (don’t use this one).

Create a NextJS project

Make sure you have Node installed on your computer. Execute this command line by replacing the example name by your own project name:

npx create-next-app notionapi-example

Once the project created, open it in your preferred IDE (VS Code for me).

Build the website

Add NextJS Image optimization

In the next.config.js file, write this:

/** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, swcMinify: true, images: { domains: ["s3.us-west-2.amazonaws.com"], }, }; module.exports = nextConfig;

Add TailwindCSS

Execute this command lines:

npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p

It will create a tailwind.config.js file. Modify it to get the same as below:

/** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {}, }, plugins: [], };

Copy these lines to the styles/globals.css file:

@tailwind base; @tailwind components; @tailwind utilities; html, body { scroll-behavior: smooth; }

Add the dependencies

Install the dependencies by running this:

npm install dotenv @notionhq/client@1.0.4

Add your integration informations

Create a .env file at the root of your project. Get your secret key on your integration dashboard. Add your integration’s key and ID like this:

NOTION_API_KEY = YOUR INTEGRATION SECRET KEY NOTION_DB_ID = YOUR DATABASE ID

Creating the API call

Notion API doesn’t allow to call it from the front-end, so we must call it from our back-end, the pages/api folder.

Create a file named articles.js in this folder and write the code to instantiate the Notion API client and parse the content of our Notion page.

require("dotenv").config(); // the following lines are required to initialize a Notion client const { Client } = require("@notionhq/client"); const notion = new Client({ auth: process.env.NOTION_API_KEY }); const databaseId = process.env.NOTION_DB_ID; export default async function getArticles() { const response = await notion.databases.query({ database_id: databaseId, }); // options for the Date format of the articles const options = { year: "numeric", month: "long", day: "numeric", }; const responseResults = response.results.map((page) => { return { id: page.id, tag: page.properties.tag.select.name, title: page.properties.title.title[0]?.plain_text, description: page.properties.description.rich_text[0].plain_text, image: page.properties.image.files[0].file.url, date: new Date( page.properties.creation_date.created_time ).toLocaleDateString("en-US", options), }; }); return responseResults; }

Clear the default page

Delete all the index.js page content, and replace it by those lines :

import Head from "next/head"; import Image from "next/image"; import getArticles from "./api/articles"; export default function Home({ articles }) { function buildArticleCards() { return articles.map((article) => { return ( <a href="#" key={article.id} className="group rounded-xl pb-5"> <div className="block overflow-hidden aspect-w-16 aspect-h-9 rounded-xl transition-all duration-200 backdrop-blur-xl backdrop-filter"> <figure className="px-10 pt-10 mt-4 relative h-44"> <Image layout="fill" src={article.image} alt={article.title} objectFit="contain" className="rounded-xl" /> </figure> </div> <div className="flex items-center mt-6 space-x-2 ml-2"> <p className="text-sm font-medium text-gray-900">{article.tag}</p> <span className="text-sm font-medium text-gray-900"></span> <p className="text-sm font-medium text-gray-900">{article.date}</p> </div> <p className="mt-4 ml-2 text-xl font-bold text-gray-900 group-hover:text-gray-600"> {article.title} </p> </a> ); }); } return ( <div> <Head> <title>NextJSxNotion</title> <meta name="description" content="Created by Yacine Messaadi" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> <h1 className="text-4xl my-10 text-center">Welcome to NextJSxNotion</h1> <section id="blogInsight"> <h2 className="text-center mt-4 font-heading font-sans text-3xl sm:text-3xl"> <span className="text-center self-center">Blog Articles</span> </h2> <div className="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl"> <div className="grid grid-cols-1 gap-10 mt-6 xl:gap-20 sm:grid-cols-2 lg:grid-cols-3 sm:mt-10"> {buildArticleCards()} </div> </div> </section> </main> </div> ); } export async function getStaticProps() { const articles = await getArticles(); return { props: { articles, }, // Revalidate is a way to rebuild the static website following an interval of seconds. revalidate: 86400, }; }

Try it out !

Start your server by writing the command below and open your browser to localhost .

npm run dev

The end

You are now able to start an amazing journey through the Notion API capabilities, mixed with the power of NextJS !