astro-notion-blogでNotionからブログ記事を書く


ここでは、Astroを用いて高速なブログを生成する [astro-notion-blog](https://github.com/otoyo/astro-notion-blog) をローカルで試す方法を、つまづいた点を含めて解説する。

## ブログ記事保存先としてのNotion

別件でブログを立ち上げようとしたが主に次の点で悩んでいた。
- GitHub上に静的サイトジェネレーターのプロジェクトごとpushする: 記事や画像が多くなると `git clone` に時間がかかる可能性がある。立ち上げの初期段階ではその見積もりが難しい。
- 画像をS3などのストレージにアップロードして使う: 記事, 画像の紐付けが煩雑になる
    - また、読み込みの転送量が従量課金の場合は万が一でもEDoS(Economy Denial of Service)が起こる可能性がある

Notionでは
 - 無料プランでブロック数無制限(文字や画像を挿入できる単位)
	 - 1ファイル5MBまで
	 - 読み込みに関する転送量については言及なし
 - アプリ連携を用いると静的サイトジェネレーターがページを生成するソースとして使用できる
 - 記事の編集時に全記事, システム一式をローカルに残しておく必要がない

と悩みを解決できているように見えた。

:::note warn
注
Notionで大量の記事を入れた際の挙動は確認していない
:::


## Notionでアプリ連携を作成する

はじめにブログの記事を保管するデータベースと、それをastro-notion-blogで取得する際のアプリ連携を設定する。

[データベースのテンプレート](https://otoyo.notion.site/e2c5fa2e8660452988d6137ba57fd974?v=abe305cd8b3d467285e91a2a85f4d8de) を開き、自分のNotion Workspaceに複製する。

次に [公式ドキュメント](https://developers.notion.com/docs/create-a-notion-integration#step-1-create-an-integration) をもとにアプリ連携を作成する。
Notionにログインした状態で [My integrations](https://www.notion.so/my-integrations)を開く。 `Create new integrations` をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/f912e235-7bd0-0d87-4baa-da1b1749961a.png)

次の項目を入力してSubmitをクリックする。
 - Type: `internal` 固定になる
 - Associated workspace: 複製したテンプレートがあるworkspaceを指定する
 - Name: わかりやすい名前をつける
 - Logo: 省略可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/c12cee3d-c449-cce0-e7bf-093cd9855d00.png)

Internal Integration Secret の画面でShowボタンをクリックし **アプリ連携のシークレット** を表示する。これはAstroビルド時の環境変数として使用する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/cd0c118f-3720-628d-c6b3-e16b698765ca.png)

## Notionでアプリ連携とデータベースを紐づける

複製したテンプレートを開き、右上のメニューから `Add connections` から作成したアプリ連携を選択して紐づける。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/81803732-79c5-5b43-11c7-510164a030fb.png)

作成した連携にデータベースを紐づける操作をしないと、Astroでのページビルド, devサーバーアクセス時に次のエラーが発生する。試した際は設定を忘れたので要注意。

```
@notionhq/client warn: request fail {
  code: 'object_not_found',
  message: 'Could not find database with ID: . Make sure the relevant pages and databases are shared with your integration.'
}
```

## NotionのデータベースIDを取得する

アプリ連携を紐づけた後は Share, `Copy link` から共有用のURLを取得するとURLがコピーされる。その他共有権限の設定などを操作する必要はない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/b39a3c37-f2d6-c520-d203-fcd908721289.png)

URLは次のようになっている。 `{A}` の部分がデータベースのIDになっているので **この部分だけをコピーする**。他の部分は不要。
```
https://www.notion.so/{account}/{A}?v={B}&pvs=4
```

## プロジェクトのセットアップ

ここではホスティングサービスにデプロイせずローカルで動作確認する方法を説明する。
astro-notion-blogのリポジトリをcloneする。

```console
$ git clone git@github.com:otoyo/astro-notion-blog.git
```

環境変数を設定する。

- `NOTION_API_SECRET`: アプリ連携を作成した際に表示された アプリ連携のシークレット
- `DATABASE_ID`: 共有用URLの一部を切りとった データベースのID

```console
$ export NOTION_API_SECRET=<YOUR_NOTION_API_SECRET>
$ export DATABASE_ID=<YOUR_DATABASE_ID>
```

最後にパッケージのインストール、devサーバーを起動してブラウザからアクセスするとNotionのデータベースからブログが生成される。
あとはAstroファイルを編集しブログの見た目を変えるなど試してみる。

```console
$ cd astro-notion-blog
$ npm install
$ npm run dev
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216963/a77144a5-574a-fee4-bd20-5094ab664d14.png)

### Node.js v21系では動作しなかった

2024-01-31現在でNode.js v21の環境だと `npm install` 時に `node-gyp`, `re2` のインストールで次のエラーが発生する。

```
npm ERR! /Users//Library/Caches/node-gyp/21.6.0/include/node/v8-local-handle.h:253:5: error: static assertion failed due to requirement 'std::is_base_of<v8::Value, v8::Data>::value': type check
npm ERR!     static_assert(std::is_base_of<T, S>::value, "type check");
npm ERR!     ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../../nan/nan_callbacks_12_inl.h:175:20: note: in instantiation of function template specialization 'v8::Local<v8::Value>::Local<v8::Data>' requested here
npm ERR!       cbinfo(info, obj->GetInternalField(kDataIndex));
```

また、Astroのdevサーバー起動時に `sharp` パッケージのエラーが発生する。
`sharp-darwin-arm64v8.node` とあるが、Apple Silicon(ARM)だけではなく、x86_64でも同様のエラーが発生したためアーキテクチャー固有の問題ではない。

```
18:40:10 [vite] Error when evaluating SSR module /src/lib/notion/client.ts: failed to import "sharp"
|- Error: 
Something went wrong installing the "sharp" module

Cannot find module '../build/Release/sharp-darwin-arm64v8.node'
Require stack:
- /Users//temporary-projects/astro-notion-blog/node_modules/sharp/lib/sharp.js
- /Users//temporary-projects/astro-notion-blog/node_modules/sharp/lib/constructor.js
- /Users//temporary-projects/astro-notion-blog/node_modules/sharp/lib/index.js
```

[このエラーに対する解決策](https://github.com/lovell/sharp/issues/2794)として `sharp@0.28.3` を導入しても別のエラーが起きて解決しなかった。

```
✘ [ERROR] No loader is configured for ".node" files: node_modules/sharp/build/Release/sharp.node

    node_modules/sharp/lib/output.js:4:22:
      4 │ const sharp = require('../build/Release/sharp.node');
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

Node.jsをLTSの20.11.0にすると上記の問題は発生しない。

## 参考

速さを追い求める人のためのNotionブログ astro-notion-blogをリリースしました - アルパカログ
https://alpacat.com/posts/introduction-of-astro-notion-blog/