ビアラテってサイトは、どんな技術を使って作ってるのかを紹介です。
なんで、ビールのサイトで技術の紹介してるかは分かりませんが、ちょっと長いので酒の肴にでもなれば良いですね。
とは言え、そこそこ専門用語が出てくるので何言ってるかわかんなかったらすみません!
ざっくり全体の構成
ざっくり全体像でいうと、次のような感じです。
- NotionをヘッドレスCMSとして活用
- Astroと言うWebフレームワークで制作
- 主な画像はCloudinaryで管理
- ホスティングサービスはCloudflare Pagesを利用
- ChatGPTは最高のパートナー
最近は、Astroでサイトを制作することが多くなっていたので、Astroの採用は特に悩みませんでした。
そして、NotionをヘッドレスCMSとして使う際、画像に有効期限が有って1時間位しか使えないのを後から知り、色々模索していた中でCloudinaryが候補に上がり採用した感じです。
Cloudflare Pagesは、ラテールのコーポレートサイト等でも使ってたので、これも特に他は考えず決定しました。
ヘッドレスCMSの選定
今回ビアラテを運営するに当たって、一番重要だったのがビールなどの情報をどこで管理するか。です。
自分一人でやったりしてるプロジェクトであれば、Markdown形式でローカルでファイル管理してるのが1番楽だったりします。
実際、自分一人で運営している「探そう!好きな恐竜」ってサイトが有るんですが、これはヘッドレスCMSとか使わずにMarkdownで完結させています。
外部サービスに依存しないのは気楽です。
- 探そう!好きな恐竜 - 子どもも楽しめる恐竜図鑑
- CGやイラストを出来るだけ多く使った恐竜図鑑みたいなサイトです。PCからだけではなく、タブレットやスマホからでも楽しんで恐竜を見つけられるようなサイトを目指しています。
しかし、今回は複数人(と言っても2人だけど)での運営を想定しなければいけないので、比較的誰でも更新しやすい環境を整えたいと思い、何かしらヘッドレスCMSを使った方が良いだろうとなりました。
その中で、記事の書きやすさ、データベースとして使える点などを考慮すると、Notionが良いのではないかと思いました。
現状弊社でも有料プランを使っていて、普段から使っていたのも採用理由の大きなポイントでした。
ちゃんとしたヘッドレスCMSの方が柔軟性の高さや構築のしやすさ等の利点は有りますが、更新するのにそのサービスにログインするのも、さぁやるぞ!ってならないと億劫になりやすかったり、料金的にもそこそこ掛かるので選択肢からは外しました。
元々NotionをヘッドレスCMSとして活用するってのに興味があったのも有りますが。
そんな感じで、Notionに決定しました。
Notionの今の構成
Notionの構成は「ビアラテ」ってページが有り、その子ページとして、
- ビール図鑑
- レビュー
- Pickup(トップページのオススメ管理用)
- ブログ
が有るって感じの構成になっています。
後は、サイトには反映されませんが、「更新・運用について」ってページも用意してます。まぁマニュアル的なやつですね。
それ以外の、運営会社や個人情報保護方針とかのページは、基本的に更新もしないし、ボクしか対応しないのでローカルにMDXで管理しています。
今後は、メーカーやブルワリーさんのちょっとした紹介ページ作成なども検討しているので、そういうのがNotion管理として増えていくような気がします。
Notion APIに苦戦
技術スタックの紹介は終わってますが、ちょっとした苦労話でも。
NotionをヘッドレスCMSとして使うと決めたは良いものの、全て手探りな感じで、色々検索して調べたりChatGPTに聞いたりして進めていました。
構築当初は、Notion+Astroというと「astro-notion-blog」がすごくヒットするので、それをベースに作ろうか?等も考えていましたが、アレはNotionっぽさを活かした感じでブログを構築することを目的としていたのと、正直コード見てもよくわからなかったので、カスタマイズするにしてもつらそうだと思い、何やかんやで1から自分で作ることにしました。
で、実際に作り始めてみると、想像の何倍も大変でした!
とりあえずNotionからデータを取得するってのは苦労しなかったのですが、Notionから取得できるデータの構造がまぁ複雑で、それらを変換するのが大変でしたね。
最初は、notion-to-md ってのを使ってNotionからMarkdownへの変換を試したのですが、対応していないブロックもそこそこ有り、なんかイマイチハマらなかったので、これも自分が使いたいブロックは一つ一つ変換するようにしました。
使ってるブロックはそこまで多くないので、実際に変換に使ってるブロックは下記くらいです。
import { renderParagraph } from './paragraph';
import { renderHeading } from './heading';
import { renderListBlock } from './list';
import { renderCallout } from './callout';
import { renderQuote } from './quote';
import { renderImage } from './image';
import { renderToggle } from './toggle';
import { renderCodeBlock } from './code';
import { renderBookmark } from './bookmark';
運用していく中で、他に使いたいのが出てきたら追加していけばいいかなと言う感じです。
それと、画像もNotionのをそのまま使うと、1時間で有効期限が切れて表示されなくなるので、ローカルにダウンロードするなり、クラウドサービスにアップロードするなりして、恒久的に使えるようにしなければなりませんでした。
これも結構悩まされました。
最終的にはCloudinaryを選びましたが、最初はダウンロードするのが良いかなとか色々考えてました。ダウンロードをやめたのは、今回数千種類のビールをいつか掲載すると言う想定が有ったので、画像枚数が膨大になるとビルドの時間がヤバそうだと思って見送りました。
このCloudinaryも初めて使うし、わからんことだらけでかなり苦戦しました。
そして、最も苦戦したのがキャッシュ周りだと思います。
開発中、毎回NotionのAPIを叩いていると負荷もすごく、そもそもがめっちゃ重くなるのでその辺をどうするか悩んだり色々試行錯誤した結果、最終的にはNotionのデータは全てMDX形式に変換してローカルにダウンロードする事を選択しました。
一度ローカルにダウンロードしてしまえば、その後はNotionとは切り離されるので、負荷になることもなく、快適に開発できました。
この方法を選択した時は、AstroのContent collectionsがv5で大幅にアップデートされて、Content Loader APIが実装されたことでリモートのコンテンツでも、ローカルのデータと同じような感じでContent collectionsが使えるっぽいことを知りませんでした。
これ使って、キャッシュも良い感じに処理すればダウンロードとかしなくても快適に開発できたかも?
とは言え、一度ダウンロードしておけば、万が一Notionが使えない自体になってもデータはMDXとしてローカルに残ってるので大丈夫ですし、逆にAstroを捨てて別のフレームワークを使ったりする際も、データはNotionに有るので、将来的な柔軟性も有るんじゃないかなと思ったりしています。
ただ、一度ダウンロードするという都合上、Notion上のデータとローカルに有るMDXのデータの整合性をちゃんと取るのが色々苦労しました。
直近でも、レビューを追加した際に、ビール側からレビューへのリンクが表示されないと言う問題が有ったりしてちょこちょこ手直ししていますが、これからも色々出てきそうな雰囲気です。
この件は、最終更新日時だけを見て判断していたのが関係していました。
レビューを更新して、リレーションでビールと紐付けているんですが、この紐付けを行ってもビール側の最終更新日時は更新されないので、更新なしとしてビール側のデータが更新されず、レビュー側だけ更新されてたので発生していました。
こうやって、慣れないNotionをCMSとして使っていると、色んな問題がバンバン出てきました。
他にも、Notion上でデータを削除した場合に同期されなかったり、Cloudinaryの画像合成がうまくいかなかったり..
…とまぁ、語り出すと終わらない気がするので、この辺で切り上げます!
終わりに
色々試行錯誤しながらですが、フロントエンドエンジニア(家で言えば、大工さん的な立場)の端くれとしては、こういった試行錯誤も楽しいので、ビール苦手なボクでもわりと楽しみながら運営できています。
お酒弱いけど、お酒自体は嫌いじゃないし、いつか★5を付けるビールに出会ってみたいものです。それもこのサイトを運営している中の楽しみの一つですね。
そんな感じで、色々やってるので不具合も出たりするかもしれませんが、ビアラテをよろしくお願いします。