Diskon kelas baru hingga 25%! Masukkan kupon "lebihcepat" di kelas ini

X
Logo Koala Skodev mengetik

Skodev

Belajar coding dalam bahasa Indonesia

MEMBUAT BLOG DENGAN NEXTJS DAN NOTION API

Yuk belajar bikin blog dengan bantuan Notion sebagai CMS. Kamu bisa membuat blog layaknya wordpress tapi dengan tampilan yang bisa kamu buat sendiri.

  Michelle Tan
Membuat Blog dengan NextJS dan Notion API

Daftar Isi:

Kenapa menggunakan Notion?
Stack yang digunakan pada tuto...
Konfigurasi Notion
Konfigurasi NextJS
Integrasi Notion dengan NextJS
Deploy ke Vercel
Penutup

Membuat blog pribadi memang menjadi kebutuhan seorang programmer. Di sana kita bisa menuliskan hal - hal yang kita pelajari atau sekedar sharing pengalaman. Saat ini, banyak yang memilih Notion sebagai platform untuk menulis konten mereka.

Kenapa menggunakan Notion?

Berdasarkan data dari Forbes pada tahun 2021, pengguna Notion sudah mencapai 20 juta. Notion sendiri merupakan platform pengelolaan konten yang memiliki banyak fitur unggulan seperti mudah untuk kolaborasi, support Notion AI, fleksibel, dan banyak fitur lainnya. Kabar baiknya, Notion juga memiliki fitur Notion API yang memudahkan kita untuk menggunakannya sebagai CMS (Content Management System) untuk blog kita.

Stack yang digunakan pada tutorial ini

Pastikan kamu sudah terlebih dahulu menginstall Node.js dan npm. Stack yang dipakai untuk tutorial ini adalah :

Disclaimer : Pada tutorial ini kita akan berfokus kepada NextJS dan Notion API. Untuk aspek tampilan visual dan SEO, teman - teman diharapkan melakukan improvisasi.

Konfigurasi Notion

Sebelum memulai konfigurasi, pastikan kamu memiliki akun Notion karena integrasi dengan NextJS memerlukan dua key, yaitu Notion Token dan Database ID

Membuat Notion Token

Tutorial cara membuat Notion Token, kamu bisa lihat tutorial atau ke halaman membuat token baru. Pada tutorial ini, saya menggunakan nama Integrasi Blog Pribadi.

Integrasi Blog Copy Notion Token dari tab Secret dan simpan dengan baik. (Keep it secret 🤫)

Setelah Notion Token terbuat, kita akan mengatur Capabilities integrasinya hanya untuk read-only, sehingga fitur-fitur lain dapat dinonaktifkan. Mengatur Capabilities pada Notion Setelah berhasil membuat Notion Token, langkah selanjutnya adalah membuat Database ID.

Membuat Database ID

Kamu bisa menduplikasi template Blog Pribadi yang ada di sini. Untuk tutorial duplikasi template, lihat pada tutorial.

Dalam template Blog Pribadi tersebut kita memiliki 7 atribute utama :

Template Notion Blog Pribadi

Setelah menduplikasi template di atas, buka template Notion di workspace kamu. Pada URL page tersebut, copy Database ID sesuai dengan posisi URL di bawah ini:

https://www.notion.so/{workspace_name}/**{database_id}**?v={view_id}

Integrasi Notion Token dengan Database

Untuk mengintegrasikan Notion Token dengan database, kita perlu menambahkan koneksi dengan cara mengklik ••• di kanan atas, lalu pilih Add Connections dan pilih Integrasi Blog Pribadi yang telah dibuat pada step sebelumnya, atau dapat mengikuti petunjuk dalam tutorial.

Menambahkan Connections pada Notion

Sampai di step ini, kita telah memiliki Notion Token dan Database ID.

Konfigurasi NextJS

NextJS adalah framework React yang memudahkan kita dalam mengembangkan aplikasi berbasis react. NextJS juga support Server Side Rendering (SSR) yang cocok untuk membuat blog menggunakan Notion API.

Untuk menginstall NextJS bisa menjalankan perintah ini pada terminal.

npx create-next-app@latest

Konfigurasi NextJS yang saya pakai tutorial ini.

√ What is your project named? blog-pribadi
√ Would you like to use TypeScript with this project? Yes
√ Would you like to use ESLint with this project? Yes
√ Would you like to use Tailwind CSS with this project? Yes
√ Would you like to use `src/` directory with this project? Yes
√ Use App Router (recommended)? Yes
√ Would you like to customize the default import alias? No

Masuk ke directory blog-pribadi dan tambahkan plugin tailwind untuk membantu proses rendering HTML khususnya bagian typograhpy.

cd blog-pribadi
npm install -D @tailwindcss/typography

Buka tailwind.config.js dan copy paste konfigurasi di bawah ini. Pada langkah ini kita hanya menghapus konfigurasi yang tidak terpakai dan menambahkan plugins yang telah kita install barusan.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {}, // Hapus theme yang tidak terpakai
  plugins: [
    require('@tailwindcss/typography'),
  ],
}

Pada step selanjutnya, kita hapus CSS class yang tidak diperlukan dan mengganti warna background pada body menjadi warna putih. Caranya bisa copy paste src/app/globals.css di bawah ini.

@tailwind base; 
@tailwind components; 
@tailwind utilities; 

body { 
	background: #ffffff; 
}

Selanjutnya hapus codingan yang tidak terpakai di halaman page.tsx sehingga menyisakan codingan di bawah ini.

export default function Home() {
  return <></>;
}

Kemudian kita run perintah di bawah ini untuk memulai project.

npm run dev

Untuk mengaksesnya project kita pada browser, kita dapat menuliskan pada URL :

http://localhost:3000

Jika tidak ada error, maka akan muncul halaman putih tanpa tulisan apa - apa. Dengan begini, kita berhasil menghapus codingan yang tidak terpakai dan siap untuk melanjutkan integrasi dengan Notion.

Integrasi Notion dengan NextJS

Kita akan menyimpan Notion Token dan Database ID yang telah kita dapatkan dengan format seperti di bawah ini pada .env.local . Jika belum ada, bisa di buat file terlebih dahulu, pastikan untuk membuatnya pada root project.

NOTION_TOKEN="secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
NOTION_DATABASE_ID="xxxxxxxxxxxxxxxxxxxxxxx"

Untuk memudahkan dalam menampilkan data Notion di project kita, maka kita perlu menginstall library Notion.

npm install @notionhq/client @notion-render/client

Membuat List Blog

Kita akan membuat tampilan list blog seperti di bawah ini. Data ini diambil dari template notion yang telah kita buat sebelumnya, dan hanya menampilkan list blog yang statusnya sudah Published.

Tampilan List Blog Buat file baru di src/app/lib/notion.tsx dan copy paste codingan di bawah ini.

const { Client } = require("@notionhq/client");

export const notion = new Client({
  auth: process.env.NOTION_TOKEN,
});

export const getAllPublishedBlog = async () => {
  const posts = await notion.databases.query({
    database_id: process.env.NOTION_DATABASE_ID,
    filter: {
      property: "status",
      select: {
        equals: "Published",
      },
    },
    sorts: [
      {
        property: "createdTime",
        direction: "descending",
      },
    ],
  });

  const allPosts = posts.results;

  return allPosts.map((post: any) => {
    return getPageContent(post);
  });
};

const getPageContent = (post: any) => {
  return {
    id: post.id,
    title: post.properties.title.title[0].plain_text,
    author: post.properties.author.select.name,
    publishedDate: post.properties.publishedDate.date.start,
    slug: post.properties.slug.formula.string,
    description: post.properties.description.rich_text[0].plain_text,
  };
};

Tambahkan file baru src/app/types/Notion.tsx untuk deklarasi types.

export type Post = {
	id: string;
	title: string;
	slug: string;
	description: string;
	author: string;
	status: string;
	publishedDate: Date;
	createdDate: Date;
}

Hapus semua codingan yang ada di page.tsx dan copy paste dari codingan di bawah ini. Pada halaman ini, kita akan memanggil getAllPublishedBlog dan me-render-nya pada halaman utama.

import Link from "next/link";
import { getAllPublishedBlog } from "./lib/notion";
import { Post } from "./types/Notion";

export default async function Home() {
  const posts = await fetchBlogData();

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div className="w-[672px] mx-auto">
        <h1 className="text-3xl font-bold mb-6">List Blog</h1>

        {posts.length === 0 ? (
          <p>No posts available.</p>
        ) : (
          posts.map((post: Post, index: number) => (
            <article
              key={index}
              className="bg-white rounded-lg cursor-pointer p-4 mb-4 border-b border-gray-300"
            >
              <div>
                <span className="text-gray-500 mb-2 text-sm">
                  {post.publishedDate.toString()}
                </span>
                <h2 className="text-xl font-semibold mb-2">
                  <Link
                    className="text-blue-500 hover:underline"
                    href={`/blog/${encodeURIComponent(post.slug)}`}
                  >
                    {post.title}
                  </Link>
                </h2>

                <p>{post.description}</p>
              </div>
            </article>
          ))
        )}
      </div>
    </main>
  );
}

async function fetchBlogData() {
  const res = getAllPublishedBlog();
  return res;
}

Membuat Detail Blog

Jika kita mengklik salah satu judul blog dari list blog yang ada, maka halaman tersebut akan pergi ke halaman Detail Blog berdasarkan slug yang dikirimkan.

Halaman Detail Blog Untuk implementasinya, kita kembali lagi file ke lib/notion.tsx dan tambahkan codingan di bawah ini.

import { NotionRenderer } from "@notion-render/client"; 

// tambahkan di bawah function getAllPublishedBlog

export const getSinglePost = async (slug: string) => {
  const response = await notion.databases.query({
    database_id: process.env.NOTION_DATABASE_ID,
    filter: {
      property: "slug",
      formula: {
        string: {
          equals: slug,
        },
      },
    },
  });

  const singlePost = response.results[0];

  const responseBlockPages = await notion.blocks.children.list({
    block_id: singlePost.id,
  });

  const content = responseBlockPages.results;
  const renderer = new NotionRenderer({
    client: notion,
  });
  const html = await renderer.render(...content);

  return {
    ...getPageContent(singlePost),
    content: html,
  };
};

Buat file baru di src/app/blog/[slug]/page.tsx dan copy paste codingan di bawah ini. Pada halaman ini kita akan me-render halaman detail blog dengan memanggil getSinglePost. Parameter slug yang ada di URL kita lempar ke dalam fungsi getSinglePost untuk mendapatkan data Notion.

import { getSinglePost } from "@/app/lib/notion";
import Link from "next/link";

export default async function Page({ params }: { params: { slug: string } }) {
  const post = await fetchBlogData(params.slug);

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div className="w-[672px] mx-auto">
        <Link href="/" className="text-blue-500">
          &lt; Go Back
        </Link>
        <div className="my-4">
		  <span className="text-gray-600">
		    {post.publishedDate} | By {post.author}{" "}
		  </span>
		</div>
        <h1 className="text-6xl text-gray-900 font-bold my-6">{post.title}</h1>
        <div
          className="prose"
          dangerouslySetInnerHTML={{ __html: post.content }}
        ></div>
      </div>
    </main>
  );
}

async function fetchBlogData(slug: string) {
  const res = getSinglePost(slug);
  return res;
}

Deploy ke Vercel

Jika semuanya sudah berjalan dengan baik, kamu bisa push codingan kamu ke github dan mendeploy ke Vercel. Pastikan Notion Token dan Database ID kamu terkonfigurasi dengan baik di Vercel.

Penutup

Untuk source code tutorial ini bisa di lihat di github.

Jika kamu ingin melakukan perubahan dalam konten blog kamu, kamu tidak perlu mengubah codingan apapun, kamu hanya perlu mengubahnya pada notion database dan perubahan tersebut akan langsung teraplikasi pada blog kamu. Selamat mencoba.

Penulis: Michelle Tan

/ @_michelletann

Hi, saya Michelle, software engineer yang suka menulis kata dan syntax.

Daftar newsletter skodev masukkan emailmu untuk dapat informasi menarik dari dunia koding