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 !
Live example here : my personal portfolio.
All the content is fetched from Notion by NextJS.
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: https://www.notion.so/my-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):
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:3000.
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 !
Top comments (3)
Great post
Thanks ! What would you like to read in the next article ?
Through our meticulously crafted website design SEO company London and cutting-edge SEO services, we equip our clients with the tools they need to not only stand out but thrive amidst fierce competition