Next.js v15 × Notionでブログ作成しました
2025/02/16 公開
はじめに
Webエンジニアとして働いてもう6年目近くになり、この2月でまた一つ歳を取るので何か新しいことを始めたいと思い、個人ブログを作成してみました。
一覧
詳細
Notionのブログ一覧
大学四年生の時も一時期WordPressとレンタルサーバーを使ってブログを書いていましたが、その時よりお金をかけずできるようになったのは本当良い時代になりましたね。👏
今回はブログ作成でNext.js ×.Notionを選んだ経緯やブログの作成手順について話していきたいと思います。
リポジトリ
使用技術
詳細は package.json 等を見ていただければと思いますが、主要どころは抜き出しておきます。
- Next.js v15.1.6
- Vercel
- Notion
- Biome v1.9.4
- postcss v8.5.1
Next.js × Notionにした経緯
フロントエンドに関しては使い慣れているNext.jsを使うことは確定していました。バックエンド領域に関してはSupabaseというものがある程度無料でデータベースを使えますし、Next.jsとの相性も良さそうだなと思いこちらを採用しました。
ただNext.js×Supabaseの構成ではCMSを自分で用意し、記事の取得だけでなく、記事の登録、更新、削除APIを作ったり、管理画面の認証の事も考えないといけなくなり、思ったより時間がかかってしまうことに作りながら気づきました…
また、Supabaseは1週間放置しているとデータベースが止められてしまうらしく、個人で試し開発で使う分には良いですが今後もずっと運用していくサービスで使っていくのは厳しそうだなということがわかりました。😓
どうしようかなと困っている時、会社の同僚に話すとNotionをCMSとして使うのはどうかという提案をもらいました。
調べてみると、
- 個人利用の場合無料でできる (5MB以上の画像をアップロードしたり、記事のバージョン履歴を1週間以上持たせたい時は課金する必要あり)
- Notionを使う事によって記事登録用の管理画面を用意する必要がなくなる
- 記事取得のAPIもちゃんと用意されている (Notionが自由自在にプロパティをカスタマイズできるのでAPIのデータ構造が複雑ではあり、ドキュメントはわかりづらい)
ということがわかったのでNext.js × Notionで実装していくことを決めました!
※ データベースを全く使わずSSGでMarkdownを配置する方法もありますが自分はCMSが欲しかったのと、バックエンドも絡めた実装がやりたかったのでこの方法は候補から外しております。
作成手順
ブログの作成手順ですが主に
- デザイン・マークアップ
- API作成・データ取得
- domain取得
で対応しました。
デザイン・マークアップ
ブログのデザインはこういうのが良いとか全く思いつかなかったので、見た目リッチな海外のブログサイトを参考にし、不要なところは削るやり方をとっています。
マークアップはPostCSSとCSS Modulesの組み合わせで行いました。理由としては、使い慣れているというのが大きいです。(tailwindのclassNameが長くなるのがどうも受け付けない😖)
ブログ詳細のマークダウンはgithubみたいな感じにしたいなーと思っていたので
を使ってCSSファイルだけぶっこ抜いて必要なところだけ使うようにしています。
API作成・データ取得
実装方法につきましてはNext.js(App Router) と NotionAPI で簡単なブログサイトを構築 を参考にしました。
全く同じやり方にするのもなんだかなあと思ったので、APIはRoute Handlersを使用して作成しました。
ただRoute Handlersにしたせいか一点詰まったポイントがあったので紹介します。
Server Componentsでfetchを使用するとfetch failedになってbuildが通らない
結論から言いますと、NextのRoute Handlersをfetchで呼ぶ時
export const dynamic = "force-dynamic"; export default async function Page() {
をpage.tsxに宣言してあげないとデフォルトの挙動で静的キャッシュ(SSG)になるのでNext.js v14以降はSSRで動いてくれないようです。
公式ドキュメントにもdynamicについてこう記載がありました。
auto
(デフォルト): コンポーネントが動的な動作を選択するのを妨げずに、可能な限りキャッシュするデフォルトのオプション。
dynamic
動的レンダリングを強制すると、リクエスト時に各ユーザーに対してルートがレンダリングされます。
このオプションは、以下と同等です。 - レイアウトまたはページ内のすべての 'fetch()' リクエストのオプションを '{ cache: 'no-store', next: { revalidate: 0 } }' に設定します。 - セグメント設定を 'export const fetchCache = 'force-no-store'' に設定します。
ドメイン取得
ドメイン取得はよく聞くものだとお名前.comとかムームードメインとかがありますが私はできる限りお金をかけたくないので、Cloudflare Registrar を利用しました。
ドメインの購入方法についてはこちらの記事を参考にさせていただきました。
ただこちらの記事に書いてあるSSL/TSLの設定は特に見当たらなかったのでそのまま進めてしまいましたが、特に問題なかったのでもう設定は不要になったのかもしれません。
Cloudflare Registarの良いところはCloudflareが手数料を追加することがなく、原価で提供するらしいので他のサイトよりは安くドメインが買えるらしいです
devドメインの価格をみると
Cloudflare 13.40ドル → 2,042円(2025/02/16時点)
ムームードメイン → 2,178円
確かに少しだけ安い…🤤
あとは手順通りに購入するだけと思っていたらCloudflare Registarでも一点問題が起きました。
クレジットカードで購入できない問題
海外サイトなので住所を海外仕様で入力し、あとはクレカで購入するだけだと思っていたのですがが何回やっても下図のエラーが出てきて購入できませんでした。
住所を厳重にチェックしているらしいので、もしかしたらその辺でエラーが発生していたのかもしれませんがわざわざ調べるのも面倒だったので諦めて、PayPalを使用して購入しました。
Cloudflare Registarを使用してドメイン購入を考えている人は気をつけてください。
最後に
Supabaseでやろうとしていた時は思ったより時間がかかり諦めかけていましたが、Notionにしたおかげでサクサク進み、3日で完成できました。費用もドメイン代の2000円だけで済みました👏
今後もエンジニアとして成長していくためや、同じ悩みを持つ人の役に立つよう、ここでやめずしっかり記事を書き続けていこうと思いますので引き続きよろしくお願いします。
Blog
FE
Next.js