キカガク プラットフォームブログ

株式会社キカガクのプラットフォームブログです。エンジニアやデザイナー、プロダクトマネージャーなどが記事を書いています。

Next.js × Notion で CMS を構築してみる

はじめに

こんにちは。株式会社キカガク、プラットフォーム部の西村です。

弊社ではドキュメントツールとして、Notion を使用しています。

そのため、NotionAPI を使って何か便利な事できないかなと思って、少し触ってみました。

この記事では、Notion で作成した DB のデータを Next.js で取得するところまでを書きます。

想定読者

  • Notion の基本的な使い方を知っている
  • とりあえず NotionAPI を使ってみたい
  • CMS 導入を検討している
  • Nextjs. 13 における API 構築について知りたい

準備( Notion 編)

NotionAPI 用に Notion データベースを作成する。

今回はアプリケーションのリリースノートを作成する体で進めます。

かなり適当ですがこんな感じで作ってみました。この辺りはお好みでカスタマイズしてください。

Notion データベース ID とトークンを取得する。

以下のドキュメントに従って、インテグレーションを作成してください。

Create integrations with the Notion API – Notion Help Center

今回私は「リリースノート」という名称で作成しました。

インテグレーションを作成すると、Integration Secret が発行されます。こちらは後ほど使用します。

インテグレーションの作成後、右上の三点リーダーから、 Add Conections を選択し、先程作成したインテグレーションと紐づけます。 表示されない場合はリロードして再度確認してみてください。

以上で Notion の設定は完了です。驚くほど簡単ですね!

最後にデータベース ID を取得します。

先程と同様に、右上の3点リーダーをクリックし、コピーリンクを選択してください。

そうすると、このようなリンクを取得できます。

https://www.notion.so/d5d24a9324b04552a52d172a73fdb2e2?v=6a9c30f189cc49baa51359c0d536ebc6&pvs=4

データベース ID は ? から直前の / までになりますので、この場合、データベース ID は、d5d24a9324b04552a52d172a73fdb2e2

となります。

準備(Next.js 編)

Next.js 13 の開発環境を準備する。

ここは割愛します。今回は App Router を使用します。

env ファイルに、準備( Notion 編)で取得した値を格納する。

今回は .env.local を作成して格納します。

notionhq/client のインストール

公式のライブラリです。以下をダウンロードしてください。

npm: @notionhq/client

以上で準備は完了です。

いざ取得

Notion のクライアントインスタンスを作成

src/app/libs/notion/notionAPI.ts

import { Client } from '@notionhq/client';

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

API 実装

src/app/api/route.ts

import { NextResponse } from 'next/server';
import { notion } from '../_lib/notion/notionAPI';

// GETメソッドのハンドラ関数
export async function GET() {
  try {
    // Notionデータベースからデータをクエリして取得
    const response = await notion.databases.query({
      database_id: process.env.NOTION_DATABASE_ID,
    });

    // データベースから取得したデータをJSONレスポンスとして返す
    return new NextResponse(JSON.stringify(response), {
      status: 200,
    });
  } catch (error) {
    console.error('データの取得に失敗しました:', error);

    // エラーレスポンスを返す
    return new NextResponse(
      JSON.stringify({ error: 'データの取得に失敗しました。' }),
      {
        status: 500,
        headers: {
          'Content-Type': 'application/json',
        },
      }
    );
  }
}

実際取得してみる

export const getAllPosts = async () => {
  try {
    const response = await fetch('/api');
    const data = await response.json();
  } catch (error) {
    console.error('データの取得に失敗しました:', error);
  }
};

この関数を実行して log を見てみるとデータが取得できていることが確認できます。

少し手を加えて、DB 作成時に作成したプロパティを返してみます。

export const getAllPosts = async () => {
  try {
    const response = await fetch('/api');
    const data = await response.json();
    if (!data) return [];
    return data?.results.map((post) => {
      return {
        title: post.properties.Name.title[0].plain_text,
        description: post.properties.Description.rich_text[0].plain_text,
        tags: post.properties.Tags.multi_select,
        status: post.properties.Status.status.name,
        date: post.properties.Date.date.start,
        slug: post.properties.Slug.rich_text[0].plain_text,
        id: post.id,
      };
    });
  } catch (error) {
    console.error('データの取得に失敗しました:', error);
  }
};

しっかり DB の値が取れていますね!

あとはフロント側の実装をしてあげればこんな感じで表示できます。

最後に

あとは動的ルーティングで詳細ページを作成し、内容を取得して表示するところまで実装すれば完璧なのですが、この辺は機会があれば書きます。

Notion を使える方であれば、導入コストはかなり低いのでオススメできます。

可能性は無限大だなと感じたので、今後も可能性を探ってみたいと思います。

現在キカガクでは、急成長するプロダクトを支えるソフトウェアエンジニアを絶賛募集中です。キカガクに興味を持ってくださった方は採用ページをご確認いただき、ぜひ一度カジュアル面談でざっくばらんにお話しましょう!