1. 概要
Notion CMS ブログとは、Notion を執筆・コンテンツ管理ツールとして使い、公開画面は別のウェブアプリでレンダリングする方式です。エディタ体験は Notion に任せつつ、デザイン、ルーティング、検索、デプロイ方式は自分でコントロールできるため、既存ブログプラットフォームの執筆のしやすさとカスタムブログの自由度を同時に狙えます。
さまざまなブログサービス(Github Pages、Tistory、Medium、Velog)
誰もがそうであるように、私も大学生の頃から勉強した内容を整理する自分だけのブログを作りたいと思っていました。Github Pages や Tistory を使おうとしましたが、以下の制約がいつも障害になっていました。
| プラットフォーム | 不便だった点 |
|---|---|
| Github Pages | 長所: カスタマイズが容易 / 短所: 執筆の手順が煩雑でエディタが使いにくい |
| Tistory | 長所: エディタ・基本機能を提供 / 短所: カスタマイズの難易度が高く、欲しい機能の開発が難しい |
文章を書くこと自体が不便だったため、だんだん書かなくなり、ブログの運営も止まってしまいました。数年後、個人の勉強やプロジェクトを進める中で、体系的に記録して後から見返せる場所が必要だと気づきました。
普段から整理に Notion をよく使っていたので、自然と Notion ベースのブログを思いつきました。ただ、単純に Notion ページを publish する方式では、デザインや機能のカスタマイズができませんでした。そこで Notion を CMS (Content Management System) として使い、デザインと機能は自分で開発することにしました。
TIP
既存ブログプラットフォームの限界を解決するために、Notion を CMS として活用した自作ブログを選びました。
2. 設計 / 構想
単純な publish ではカテゴリ・タグ検索などの便利な機能を提供しにくかったため、Notion を CMS に据えて企画から開発まで自分で行うことにしました。企画は退勤後の空き時間に進め、約1ヶ月かかりました。
コンポーネントデザインの前に、ブログの配色を決める際に v0.dev でカラーパレットを作り、友人たちに意見を求めました(背景色は自分で決めました)。
v0.dev で描いたカラーパレット
その後、**最小単位のコンポーネント(Typography、Button など)**から始めて拡張していく構成でデザインを進め、友人たちのフィードバックをもとに修正を繰り返しました。
NOTE
配色とコンポーネント単位のデザインを先に固めてから拡張する方式は、その後の開発速度を上げるのに役立ちます。
Figma で自分で描いたブログのコンポーネントデザイン
コンポーネントをもとに作ったページデザイン
3. 開発 / 実装
このプロジェクトは Figma MCP + Github Copilot を使った Vibe Coding 方式で進めました。
Figma と Github Copilot
Figma でデザインしたコンポーネントの URL を入れるだけで(事前設定が必要)、Github Copilot がコンポーネントのコード、Storybook、テストコードを書いてくれました。
├── PostRow
│ ├── PostRow.stories.tsx
│ ├── PostRow.test.tsx
│ ├── PostRow.tsx
│ └── index.tsx
└── TagList
├── TagList.stories.tsx
├── TagList.test.tsx
├── TagList.tsx
└── index.tsxただ、FE の経験が浅かった私にとっては、Vibe Coding の間も悩みが尽きませんでした。
「Props の設計は今やるべきか、後にするべきか?デザイン要素から開発すべきか?ダークモードはいつ作るか?Notion のデータロジックを先に実装すべきか?」
とにかくぶつかりながら、数えきれない試行錯誤とリファクタリングを重ねました。Vibe Coding の特性上、AI が書いたコードが意図と異なる動作をすることがあるため、品質維持のために CI 環境に力を入れました。
3.1. Storybook & テストコードの義務化
copilot-instructions.md に「コンポーネント実装時は必ず Storybook とテストコードを書くこと」を明記し、codecov.yml でテストカバレッジ 80% 以上を目標にしました。
coverage レポートの例
3.2. Github Actions ベースの自動テスト
PR を出すと Github Actions が自動的にテストとビルドを実行するように設定しました。ビルド + テスト + 静的解析がすべて通らないと main に merge できないようにして、壊れたコードがマージされる最悪の事態を防ぎました。
Github Checks の項目
3.3. Dependabot を使ったパッケージ管理
dependabot.yml に更新ルールと auto-merge の可否を定義し、依存関係を定期的に更新しました。おかげで古いライブラリの放置を防ぎ、セキュリティパッチも素早く適用できました。
dependabot + auto-merge による dev パッケージの自動更新
4. デプロイ
デプロイ方式は長く悩んだ部分です。最初は自前サーバーへのデプロイを考えましたが、ブログは静的(static)ビルドだけで十分で、あえてサーバーを用意する必要はありませんでした。そこで Github Pages を選び、Notion の記事をビルド時に静的に変換した成果物をデプロイする方式にしました。
ところが、ビルドを実行するたびに Notion データを取得する部分で timeout が発生しました。原因が分からずにいましたが、react-notion-x の Notion ページ fetch の動作と関連事例を調べたところ、collection/database があるページで fetch が止まりうるという背景がありました。
NOTE
(2025.09.29 時点)react-notion-x 7.6 バージョンで該当の fetch 問題が解決され、もう発生しません。
提案されたとおり react-notion-x を特定バージョンにダウングレードするとビルドが正常に完了し、ついに自作の Notion CMS ベースのブログをデプロイできました。
WARNING
静的ビルドでのデプロイを選ぶ際は、使用するライブラリのビルドタイムの動作まで事前に検証しておくことが重要です。
5. まとめ / 振り返り
最初は2ヶ月で終わると思っていましたが、企画が長引き個人的な事情も重なって、合計4ヶ月かかりました。それでも退勤後の空き時間で完成させ、デプロイまでやり遂げられて嬉しかったです。今年の目標だった年間サイドプロジェクト2つのうち1つを終え、初めての React ベースの FE プロジェクトで、より良いプロセスや構成について考えることができました。
まだ残っている機能もあります(いつか実装予定です)。
- About ページ
- ToC (Table of Contents)
- Fuzzy Search
最後に、企画・デザイン・機能の一つひとつにフィードバックを惜しまなかった友人たちに感謝の言葉を伝えたいです。
TIP
Vibe Coding は生産性を高めてくれますが、設計の検討と CI の構築は依然として開発者の仕事でした。次のプロジェクトでは、序盤の設計にもっと時間を投資する予定です。