背景
Qiita Engineer Festa 2024への参加記録のポータルを自前でつくりたいなあ……
最近使って、少しはわかるAstroでサイトをつくるか……
でもデータベースの立ち上げとか、データを入力するためのフォームをつくるとかやっていると、イベント終了まで終わらないな……
あー、入力しやすいからNotionのデータベースでいいか……
――ということで、Astro製のサイトでNotionのデータベースのデータを表示することをしてみます
具体的には、
- NotionにQiita Engineer Festa 2024の投稿記録データベースを作成します
- Astroで一枚ものサイトを立ち上げます
- Notion APIでデータベースのデータを取得します
- 取得したデータを表示し、投稿記録のスタンプカードと投稿リストを表示します
といったところです
Qiita Engineer Festaならすでにスタンプカードあるじゃんとか言わないでください
知っている知識で何かつくりたくなるのがエンジニアなのです、多分
大事なこと
これから書く内容でつくったサイトはインターネット上への公開を前提にしていません
純なAstroコンポーネントでつくるため、ビルド時にNotion APIで取得した内容でサイト内のデータが決まります(その後、Notionデータベースを更新しても、変更はサイトに反映されません)
必要なら、エンドポイントとかVueコンポーネントとか、動的にNotion APIにアクセスして表示するようなそういうあれこれでつくる必要があります
余裕と気力が続けば、これはのちのちに対応したいと思いますが、今回は対応しません
記事の構成
一気に記事を書ききる気力がないため、今回はNotion APIからデータを取得するところまでとなります
二つ目の記事がAPIから取得したデータの加工、三つ目の記事がデータの表示となる予定です
前準備
では、まずはNotionにデータベースを準備します
項目名は、Title
(投稿名)、Published
(投稿日)、Tags
(おおざっぱなタグ、複数)、Status
(投稿状況)、Url
(投稿のURL)とします
項目名を日本語にすると、Notion APIでデータを取得したとき、キー名が日本語になって気持ち悪かったので、アルファベットでリネームしました
(リネームすると、APIから取得できるデータが即時書きかわりました 反応が良すぎて気味悪かったです)
後々の利便性のため、および、目標達成のために、データベースには目標38記事分のデータをあらかじめつくっておき、StatusをCompleted
(投稿済み)、In_progress
(作業中)、Not_started
(未着手)として、管理することにしました
また、Published
(投稿日)は、予定にもとづいて適当な日付を突っ込みました(1日3件書くというアホみたいな予定です)
これも、サイトをつくっていたら、日付が空なデータがあるとちょっと困ったことがあったための対応です
下準備はこれで完成です
続いて、サイトを作成していきます
サイト立ち上げ
Astroの公式サイトのGetting Startedから、開始します
コマンドを走らせれば、パッケージもろもろ準備してくれます
npm create astro@latest
実行記録
> npx
> create-astro
astro Launch sequence initiated.
dir Where should we create your new project?
.
tmpl How would you like to start your new project?
Empty
ts Do you plan to write TypeScript?
Yes
use How strict should TypeScript be?
Strict
deps Install dependencies?
Yes
git Initialize a new git repository?
Yes
✔ Project initialized!
■ Template copied
■ TypeScript customized
■ Dependencies installed
■ Git initialized
next Liftoff confirmed. Explore your project!
Run npm run dev to start the dev server. CTRL+C to stop.
Add frameworks like react or tailwind using astro add.
Stuck? Join us at https://astro.build/chat
実行記録
> dev
> astro dev
15:48:27 [types] Added src/env.d.ts type declarations.
15:48:27 [vite] Port 4321 is in use, trying another one...
astro v4.11.5 ready in 681 ms
┃ Local http://localhost:4322/
┃ Network use --host to expose
15:48:27 watching for file changes...
15:49:52 [200] / 13ms
ここで一度、GitHubに入れておきます
.gitignore
は準備してもらったので、普通にコミット? プッシュ? なんだろう、何かして送信すればOKです
Notionへのアクセス
もう少し下準備が必要でした
Notion APIでアクセスするための設定とトークンの取得です
Notionの「設定」から「コネクト」で「インテグレーションを作成または管理する」へアクセスします
「新しいインテグレーション」から、
- インテグレーション名:任意の名前を指定
- 関連ワークスペース:準備したデータベースのあるワークスペースを指定
- 種類:「内部」を指定
を設定し、保存します
すると、インテグレーションの管理画面に飛べるので、そこから「内部インテグレーションシークレット」でアクセストークンを取得します(トークンは後ほど使うので控えておきますが、後で必要なタイミングでアクセスして取得しても問題ありません)
「機能」の「コンテンツ機能」は「コンテンツを読み取る」だけで今回はじゅうぶんなので、更新、挿入のデフォルトのチェックを外します
「ユーザー機能」も「ユーザー情報なし」でいいので、設定します
続いて、今作成したインテグレーションから目的のデータベースにアクセスできるようにします
Notionのデータベースを表示し、右上のメニューから、「コネクト」、「接続先」で今作成したインテグレーションを選びます
それから、データベースのIDも取得しておきます
IDの取得の仕方は以下のページの"Where can I find my database's ID?"をご参照ください
目的のデータベースをフルページで開いたときのURLがhttps://www.notion.so/{workspace_name}/{database_id}?v={view_id}
となっていますので、それで取得できます
はい、これで下準備は本当に終わりです
AstroでNotion APIにアクセスする
Astroのサイト開発に戻ります
今回は一枚もののページですし、スピード重視でsrc/pages/index.astro
にべた書きしていきます(普通はコンポーネントわけしたほうがいいです)
Notion APIにはAPIアクセス向けのクライアントのパッケージが存在するので、それを導入します
npm install @notionhq/client
実行結果
added 14 packages, and audited 436 packages in 4s
165 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
まずは、アクセスしてみます
以下はエラー処理とか何も考えていないコードです
IDやトークンもべた書きしているので、決して真似してはいけません
PublicなGitHubリポジトリとかに投稿してしまった場合は、即時どうにかして削除しましょう
---
import { Client } from "@notionhq/client";
const database_id = "********";
const auth_key = "********";
const notion = new Client({ auth: auth_key });
const data = await notion.databases.query({ database_id });
const articles = data.results;
console.log(articles);
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
</body>
</html>
これで以下のようなデータを取得できることが確認できました
console.logの表示
[
{
object: 'page',
id: '*',
created_time: '2024-07-05T05:13:00.000Z',
last_edited_time: '2024-07-05T05:13:00.000Z',
created_by: { object: 'user', id: '*' },
last_edited_by: { object: 'user', id: '*' },
cover: null,
icon: null,
parent: {
type: 'database_id',
database_id: '*'
},
archived: false,
in_trash: false,
properties: {
Status: [Object],
Tags: [Object],
Url: [Object],
Published: [Object],
Title: [Object]
},
url: 'https://www.notion.so/*',
public_url: null
},
{
object: 'page',
id: '*',
created_time: '2024-07-05T05:13:00.000Z',
last_edited_time: '2024-07-05T05:13:00.000Z',
created_by: { object: 'user', id: '*' },
last_edited_by: { object: 'user', id: '*' },
cover: null,
icon: null,
parent: {
type: 'database_id',
database_id: '*'
},
archived: false,
in_trash: false,
properties: {
Status: [Object],
Tags: [Object],
Url: [Object],
Published: [Object],
Title: [Object]
},
url: 'https://www.notion.so/*',
public_url: null
},
(略)
ここまで来れば、後はこれらのデータを適当に加工して、表示するだけです
しかし、APIで取得してきたデータはプロパティが多くて扱いづらいので、必要なデータを抜き取ったデータをつくったほうがよさそうでした
ということで、次は「データの加工」でおこなったことを記事にします
後書き
この手の開発は瞬発力が求められるのでしょうが、知識不十分な素人のため、調査しながらだと、なかなか思うように進みません
上記くらいの内容で、半日くらいかかりました
これからの課題は、
- fetchの適切なエラー処理
だと思っていますので、少しずつ調べていきます