iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Modern Web

製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~系列 第 11

#11 No-code 之旅 — 在 Next.js 專案中顯示 Notion 的資料 ft. Notion SDK

  • 分享至 

  • xImage
  •  

哈囉!昨天使用 SWR 實作了一個小功能,讓使用者可以列出某 Github user 的所有公開 repository~ 今天用 Notion SDK 新增了一個新的頁面,顯示我的 Notion page 裡面的內容,可以在這裡看看喔。

Notion SDK

Getting Started

想要可以用 Notion SDK 或呼叫 Notion API 之前,我們要去做這些步驟取得權限:

  1. 新增一個 integration
    • My Integrations
    • 按 "+ New Integration" 按鈕去
    • 輸入需要的資料,例如 integration 名稱,選 workspace
    • 按 "Submit" 送出,新增完了!
    • 現在把 "Internal Integration Token" 裡的 secret 複製下來,放在安全的地方,我們之後會用到~
  2. 把 page 分享給 integration
    • 到你想要取得資料的 Notion page,像我的是這一頁
    • 按 "Share" 打開分享小視窗
    • 點輸入匡,會有新的小視窗出來
    • 裡面應該會看到你剛新增的 integration
    • 選該 integration 然後按 "Invite"
  3. 複製你的 Notion page ID,像我的 URL 長這樣 https://jadejs.notion.site/iTHome-0f3a86530c5e44d18004c5c689044c5d- 後面的一串字串是我們想要的 ID
  4. 把 secret token 和 page ID 寫在 .env 檔裡面
    NOTION_TOKEN=secret_**********************************
    NOTION_PAGE_ID=0f3a86530c5e44d18004c5c689044c5d
    
    page ID 其實是公開的資訊,所以不一定要放在 .env 裡~

Setup

我們現在要安裝 Notion SDK,如果你們想要用 Notion API 也可以喔!不過我在這專案裡使用的是 SDK:

npm install @notionhq/client
# or
yarn add @notionhq/client

裝完之後我們可以開始用 SDK 了~

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

// 初始化 Client
const notion = new Client({
  auth: process.env.NOTION_TOKEN, // 剛剛把 secret token 寫在 .env 裡面的那個!
});

取得 Page 資料

豪!可以開始拿資料了~ Notion API 有提供很多 endpoints,例如我們今天要用的 pages.retrieve,就是取得該 page 的內容。

export const getPage = async () => {
  const pageId = process.env.NOTION_PAGE_ID; // 我們的 page ID
  const response = await notion.pages.retrieve({ page_id: pageId });

  // response 會是 page object
  return response;
};

response 為 JSON 格式的 page object:

{
  "object": "page",
  "id": "b55c9c91-384d-452b-81db-d1ef79372b75",
  "created_time": "2020-03-17T19:10:04.968Z",
  "last_edited_time": "2020-03-17T21:49:37.913Z",
  "parent": {
    "type": "database_id",
    "database_id": "48f8fee9-cd79-4180-bc2f-ec0398253067"
  },
  "archived": false,
  "url": "https://www.notion.so/Avocado-b55c9c91384d452b81dbd1ef79372b75",
  "icon": { "type": "emoji", "emoji": "?" },
  "cover": {
    "type": "external",
    "external": {
    	"url": "https://website.domain/images/image.png"
    }
  },
  "properties": {...}
}

使用 pages.retrieve 並不會拿到該 page 的 blocks (page 的內容),只會拿到 page 的一些資訊和 properties
Working with page content

圖片來源:Working with page content

所以我們拿不到上面圖中的連結和文字,可是我們會拿到 titleActor,還有封面圖,新增編輯時間等。

取得 Blocks

export const getBlocks = async () => {
  // page 也是一種 block
  const blockId = process.env.NOTION_PAGE_ID;
  // 我們想拿到 page 裡的 blocks,這裡 block_id 等於 page ID
  const response = await notion.blocks.children.list({ block_id: blockId });

  // response 為 list of blocks
  return response;
};

以上面的圖為例子,我們會拿到三個 blocks,第一個是連結,第二個是 Synopsis,第三個是 paragraph。

Notion 頁

如果以上面的圖為例子,就是我今天做的頁面,我們大概會拿到像這樣的 response

{
  "object": "list",
  "results": [
    {
      "object": "block",
      "id": "c164f4b2-ad9e-45df-859c-bbb5759eff00",
      "created_time": "2021-09-26T08:42:00.000Z",
      "last_edited_time": "2021-09-26T08:42:00.000Z",
      "has_children": false,
      "archived": false,
      "type": "heading_1",
      "heading_1": {
        "text": [
          {
            "type": "text",
            "text": { "content": "2021 鐵人賽 | iT邦幫忙", "link": null },
            "annotations": {
              "bold": false,
              "italic": false,
              "strikethrough": false,
              "underline": false,
              "code": false,
              "color": "default"
            },
            "plain_text": "2021 鐵人賽 | iT邦幫忙",
            "href": null
          }
        ]
      }
    },
    {
      "object": "block",
      "id": "0f707dff-1498-4416-a156-7c6ef2a026d1",
      "created_time": "2021-09-26T08:42:00.000Z",
      "last_edited_time": "2021-09-26T08:42:00.000Z",
      "has_children": false,
      "archived": false,
      "type": "heading_3",
      "heading_3": {
        "text": [
          {
            "type": "text",
            "text": {
              "content": "製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~",
              "link": null
            },
            "annotations": {
              "bold": false,
              "italic": false,
              "strikethrough": false,
              "underline": false,
              "code": false,
              "color": "default"
            },
            "plain_text": "製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~",
            "href": null
          }
        ]
      }
    },
    ...
  ],
}

每個 block 會有 idtype,新增編輯時間等,也包含該 block 的內容,像 heading_3 的 block,裡面包含了 text 的陣列,每一個 text object 會有自己的格式 (formatting),寫在 annotations 裡面。我們可以根據 annotations 還有 href 的資訊決定該怎麼顯示這個 text object (物件)~

用 Data Fetching 方式抓取資料

今天使用了 getStaticProps 抓取資料,可是也可以用 getServerSideProps,而且用 SSR 的話,頁面可以拿到最新的內容!不過我這頁面內容應該不會變,所以決定這麼寫:

// pages/notion.js
export async function getStaticProps() {
  // 可以直接把 getPage 和 getBlocks import 進來~
  const page = await getPage();
  const blocks = await getBlocks();
  const data = { ...page, blocks };

  return {
    props: { data },
  };
}

小結

今天看了 Notion API 的文件,發現抓完資料還要做多處理!不過這也讓我們有更多的彈性,想怎麼顯示我們拿到的資料都可以~ 所以我從一開始打算把 Notion 當成 CMS 或是資料庫,把資料都寫在 Notion 裡,然後再用 API 取這些資料去顯示。今天的小功能有讓我覺得好像離目標更近一步了!XD
大家可以看看在這裡,然後 Notion 的 page 在這裡

祝大家週末愉快!

Live Demo

晚安 <3

看更多


上一篇
#10 實作篇 — 使用 SWR 抓取和 Cache 資料
下一篇
#12 No-code 之旅 — 在 Next.js 專案中顯示 RSS 的資料 ft. RSS Parser
系列文
製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言