アドベントカレンダーって、
期限が決まっていて、自分がやると宣言したのだから、切羽詰まって進捗出ますよね!
これを書き上げているのも公開日前夜!
このギリギリを責める感じ、自分の計画性のなさが露呈します。
「期限を決めて、宣言して自分を追い込む。」
計画性のない人間にとっては必要なことだと思うのです。
これが12月だけって、ちょっともったいない気がしませんか?
いつでもできるアドベントカレンダー、必要だと思いませんか?
せっかくなので、それをJamstack構成で作っちゃおうというのがこの記事です。
だいたい入力にはHeadlessCMSとかそういったものを使用すると思うのですが、今回は前から気になっていたNotionをCMS代わりに使ってみたいと思っています。
成果物
https://pocchi-adventcalendar-2020.netlify.app/202012
https://github.com/Pocchi/advent-calendar2020
ちなみに、かわいいお猿さんはこちらからお借りしました。
Notionにデータベースを用意する
Default Viewとして、Tableを用意しました。
「全てを自分で書くんだ!」という強い気持ちを持たせるために、writer欄を用意して、自分を入れました。
ここで注意するのが、urlもTextで用意することです。
URLもあるのですが、APIを通してデータを取得した時に、Not Supported
の文字列が入ってきてしまいます。
Notionからデータを取得する
Notionをブログとして公開する、notion-blogという素敵なものもありますが、
今回はDBとしてNotionを使用したいので、こちらの記事を参考にしました。
現在、Notionの公式なAPIはないようで、非公式なものを使います。
使用したのはnotion-api-workerです。
参考記事を見て、
データを取得したいNotionのページのURLからPAGE_ID
を、Cookie(token_v2)からTOKEN
を拾ってきました。
const { data } = await $axios.get(
`https://notion-api.splitbee.io/v1/table/${process.env.PAGE_ID}`,
{
headers: { Authorization: `Bearer ${process.env.TOKEN}` },
}
)
これでデータを取得できました。
配列の中にオブジェクトで入ってきます。
[
{
id: 'e937a6ac-1d98-48d8-8e03-e6486d3f2118',
date: '2020-11-16',
writer: '自分',
url: 'https://www.google.com/',
comment: '何か'
},
{
id: '513c77a3-121a-4792-ab1f-294e760c11e1',
date: '2020-12-11',
writer: '自分',
comment: '何か2'
}...
]
Nuxtでカレンダーを作る
Nuxtのverとモードはこちら。
target: static
で使用しています。
╭───────────────────────────────────────╮
│ │
│ Nuxt.js @ v2.14.7 │
│ │
│ ▸ Environment: development │
│ ▸ Rendering: server-side │
│ ▸ Target: static │
│ │
│ Listening: http://localhost:3000/ │
│ │
╰───────────────────────────────────────╯
できた画面としてはこんな感じ。
https://5fcb40ea07edeeb8b84e8a4a--pocchi-adventcalendar-2020.netlify.app/202012/
vuetifyのカレンダーを使用しました。
通常であれば、<前の月
や次の月>
のように遷移するボタンを用意するのですが、今回はヘッダにデータのある月のリンクだけ用意しています。
URLの指定
localhost:3000/[YYYYMM]
のようにURLに年月を渡して、その月のカレンダーを表示しています。
APIから取得して動的に生成するURLなので、nuxt.config.jsでgenerateを指定する必要があります。
(指定しないとページが生成されず、直アクセスで404になってしまいます。)
Nuxtのv2.13から
ページに貼ってあるリンクからクロールして勝手にページを生成してくれるようになったので、1つのページだけとりあえず指定しておけば問題ないです。(参考)
generate: {
routes() {
return ['/202011']
},
},
これだけでリンクを貼っている3ページ分が静的に生成されました。
余談ですが、リンクの値を間違って貼ってしまうと、generate時にエラーが起きてしまいますので気をつけましょう。(自戒。原因が分からず、調査してクロールに気づきました。数時間溶けた。)
Netlifyでホスティングする
ローカルで環境変数をdirenvで使っていたのですが、Netlifyの方でも設定が必要です。
(すっかり忘れていてページの生成時にAPIにアクセスできずに500になってしまいました。) ちなみに、Nuxt.jsの困ったところなのですが、500でページの生成が失敗したとしても、正常終了してそのままデプロイしてしまいます。 ![スクリーンショット 2020-12-05 17.36.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48488/c264582e-4fb2-fcb7-5665-0b3d6b8dfd34.png)オプションでエラー時にビルドを失敗させることができるので、--fail-on-error
をつけておいた方が無難です。
あと、keyの隠蔽は忘れずにしておきましょう。
PAGE_IDとTOKENがあれば誰でもデータが取得できてしまいます。
こちらの記事を参考に、production時はprivateRuntimeConfig
でビルド時のみkeyを参照できるようにしました。
今後のロードマップ(未定)
webhook
ちゃんと運用していくためにはNotionを更新したらNetlify側でデプロイするようなwebhookの設定が必要です。
ちょっとだけ調べてみたのですが、Notion側からデプロイをアクションするための、ブラウザ拡張を自作するようなアプローチを見つけました。
https://github.com/dragonman225/trigger-webhook-from-notion
POST
Notionを更新せず、DBとしてだけ使えないのか?と考えています。
GETだけでなく、POSTもしてみたい。
以下を読んでみたところ、できそうかな・・と思いましたが、とりあえず思っただけです。
https://github.com/jamalex/notion-py
https://tomohisaoda.com/posts/2020/notify-public-page-on-notion-to-slack.html