このページの本文へ

FIXER Tech Blog - Development

技術ブログを書きたくなったので、Cloudflare+Next.jsで丸ごと自作してみた

2026年01月20日 15時00分更新

文● 江藤皓史/FIXER

  • この記事をはてなブックマークに追加
  • 本文印刷

 本記事はFIXERが提供する「cloud.config Tech Blog」に掲載された「テックブログを書きたくなったのでサイトから作ってみた」を再編集したものです。

はじめに

お疲れ様です。

今年もアドベントカレンダーの季節になり、何か面白いことをしたいと思いました。

業務での学びや技術的な試行錯誤をまとめられる個人的な場所が欲しかったこともあり、ブログサイトを自作することにしました。

既存のブログサービスを使うことも考えましたが、自分でデザインや機能を考えたかったので、ゼロから作ることにしました。

この記事では、コンセプトづくりや Figma を使ったモック作成、技術選定、Next.js と Cloudflare を中心とした実装プロセスをまとめています。なお、紹介する方法は必ずしも「ベストプラクティス」ではないことをご了承ください。

コンセプトづくり

サイトとしてのコンセプト

ブログサイトを作るにあたって、まずは大まかな方向性を整理します。

今回作成するブログサイトは「気軽にかけて、気軽に読める技術ブログ」をコンセプトにしています。

機能を盛り込みすぎず、まずは以下3点を満たすことを目標にしました。

1. 読みやすいこと

技術記事は内容が中心になるため、装飾を控えめにし、余白やフォントのバランスを優先しました。

2. 更新しやすいこと

記事投稿フローをできるだけシンプルにし、編集画面や構成も自分が迷わない形にしました。

3. 長く使えること

必要に応じていつでも拡張できるよう、設計をシンプルに保つようにしました。

Figma でのデザイン

コンセプトが固まった段階で、Figmaを使ってデザインを具体化しました。

ブランドカラーには深めのグリーンを採用し、背景やテキストには落ち着いたトーンを合わせて、読みやすさを損なわない配色にまとめています。

続いてワイヤーフレームを作成し、このワイヤーフレームとカラーパレットをもとにモックアップを作成しました。

レスポンシブ対応も考慮して、モバイル・タブレット・PCの3デバイス分を用意しました。

さらに、作成したモックアップを使って画面遷移をまとめたフロー図を作成し、必要な導線やデータの流れを視覚化しました。

Figma 上でモック・カラー・ロゴを先に固めたことで、Next.js のコンポーネント構成や CSS 設計の方針が明確になり、実装段階で迷う時間が少なくなったと感じています。

技術選定

実装に入るにあたって、今回必要になる技術を整理しました。

普段はアプリケーション側の開発を担当していることもあり、今回もアプリ側の実装を中心に進めることを前提としています。

そのため、インフラ周りは必要最低限の設定で済み、かつ運用負荷が小さく扱いやすいサービスを選びたいという背景がありました。これらの条件に最も合っていたのがCloudflareでした。

どこででも接続、保護、構築 | Cloudflare

フロントエンドにはNext.jsを採用しました。

App Routerとサーバーアクションを使うことで、APIサーバーを別途用意する必要がなく、記事投稿や編集といったCRUD操作を簡潔に実装できる点が大きなメリットでした。

Next.js by Vercel - The React Framework

アーキテクチャ設計

今回のブログサイトは、できるだけシンプルな構成で運用できることを意識して設計しました。

大きく分けると、Next.js側のアプリケーションCloudflare側の基盤サービスの2つに役割を分けています。

全体構成

ざっくりとした構成は以下のようなイメージです。
・フロントエンド:Next.js(App Router)
・サーバーサイド処理:Next.js のサーバーアクション
・データベース:Cloudflare D1
・画像・アセット:Cloudflare R2
・認証/保護:Cloudflare Access
・配信・エッジ:Cloudflare(CDN / Workers)

Next.jsが画面表示とサーバーアクションを担当し、データの永続化や静的ファイルの配信などを Cloudflare側に任せる形にしています。

データフロー

記事の取得と投稿の流れはざっくり以下のような感じです。

・記事の取得
 1. ユーザーが記事一覧/詳細ページにアクセス
 2. Next.jsのサーバーコンポーネント or サーバーアクションからD1にクエリ
 3. 取得したデータをページにレンダリング

・記事の投稿・更新
 1. 管理画面からフォームを送信
 2. サーバーアクション経由でD1に対してINSERT / UPDATE
 3. 必要に応じてR2に画像をアップロードし、そのパスを記事データに紐づける

 今回はAPIサーバーを別で用意せず、「Next.jsのサーバーアクション → D1」 というシンプルな動線にしています。

記事データ構造

記事データは、D1上にシンプルなテーブルを1つ用意して管理しています。

基本的なカラムとしては、タイトル・本文・スラッグ・公開フラグ・作成/更新日時など、ブログとして最低限必要な情報に絞っています。

セキュリティ設計(Accessを使った管理画面保護)

管理画面については、アプリ側でログイン機能を実装するのではなく、Cloudflare Accessを使って保護する構成にしています。

・管理画面にアクセスする前にAccessが認証を実施
・許可されたユーザーのみが管理画面に到達できる

これによって、アプリケーション側で認証機能を一から実装せずに済み、個人開発でも比較的安全な形で管理画面を公開できるようにしています。

Cloudflare の構成

今回のブログでは、インフラまわりの実装や運用コストをできるだけ小さくしたかったため、Cloudflareのマネージドなサービスに寄せて構成を組みました。Workers、D1、R2、Access の4つを組み合わせて利用しています。

Workers

Workersは、サーバーレスでJavaScriptを実行できるエッジプラットフォームです。

Cloudflare Workers | サーバーレスアプリケーションを構築 | Cloudflare

以前は静的アセットをCloudflare Pagesでホストして、動的なサーバー処理をWorkerで使用するような構成が一般的でしたが、2024年9月のアップデートにより、Pagesの機能がWorkerに統合される形になり、単一Workerでフルスタックアプリケーションを構築することが可能になりました。

主に配信まわりやNext.jsの動作基盤として利用しており、特別な設定をしなくてもCloudflareのエッジで高速に動いてくれる点が便利でした。

D1

D1はSQLiteベースのサーバーレスなマネージドデータベースです。

ネイティブにサーバーレスなSQLデータベースをCloudflare D1で構築 | Cloudflare

スキーマを作り、Next.jsのサーバーアクションから直接クエリを発行するだけでCRUD処理が完結します。

大規模なデータ構造を必要としなかった今回のブログにはちょうどよい選択でした。

今回は記事データの保存に利用しています。

R2

R2は、オブジェクトストレージです。

Cloudflare R2 | エグレス料金ゼロのオブジェクトストレージ | Cloudflare

記事内で使用する画像のアップロード先として利用しています。AWS S3互換のAPIで扱いやすく、コストも低いので、個人開発としてはとても使いやすいストレージでした。

記事の投稿時にR2に画像をアップロードし、そのURLを記事データに紐づけるだけで運用できます。

Access

管理画面の保護には、Cloudflare Accessを使用しています。

Access | ゼロトラストネットワークアクセス(ZTNA)ソリューション | Cloudflare

アプリ側でログイン機能を実装すると工数がかかるため、Access側で認証を完結できるのは非常に助かりました。

ポリシーの作成により、許可されたユーザーだけが管理画面にアクセスできるようになるため、個人開発でも比較的安全な運用ができます。

Cloudflare を使ってみて

Cloudflareを選んだ理由は「設定が少なく、必要な部分だけを最低限使える」点でしたが、D1を使ったデータ管理、R2を使った画像保存・Accessによる管理画面の保護など、欲しい機能がシンプルに組み合わせられるため、アプリ側の実装に集中できる環境が整えやすかったです。

アプリ側の実装

フロントエンドの実装

フロントエンドはNext.jsを使って実装しました。

Figmaで作成したモックをベースに、UIコンポーネント → 機能コンポーネント → ページの順番で組み上げています。

まずはUIの土台を整えるため、Storybookを使ってUIコンポーネントの単体開発から着手しました。ボタン・入力欄・カードなど、ブログ全体で再利用する要素を先に整えておくことで、その後の開発がかなりスムーズになりました。

UIコンポーネントのデザインは、デジタル庁デザインシステムを参考にしています。アクセシビリティや視認性が重視されたデザイン体系なので、ブログのように読むことが中心になるUIとは相性が良く、余白や文字サイズ、フォーカス状態などを踏襲しながら調整しました。

デザインシステム|デジタル庁

UIが揃ったら、続けて機能コンポーネント(記事一覧の取得・検索機能・プレビュー表示など)を実装し、最後に各ページで必要な処理を組み合わせてページ全体を仕上げていきました。

バックエンドの実装

今回はNext.jsのサーバーアクションを入口にして、記事のCRUDや画像アップロードなどのサーバー処理をまとめました。

別途APIサーバーを立てずに、フォーム送信をそのままサーバー処理に繋げられるのが大きなメリットです。

具体的には、フォームのactionにサーバーアクションを指定するだけで、次のような処理を実装できます。

・記事の作成 / 更新 / 削除
・記事一覧・詳細の取得
・画像アップロード(R2)との連携

サーバーアクションはuse serverを付けた関数として定義し、その中でD1へのクエリやR2へのアップロードを行っています。

リクエスト/レスポンスのための API ルートや型定義を大量に用意せずに済むので、管理画面のような用途では実装がかなりシンプルになりました。

管理画面の実装

管理画面では、以下の操作を行えるようにしています。

・記事一覧の表示
・記事の編集
・新規記事の作成(プレビュー付き)


管理画面はApp Routerのサーバーコンポーネントを中心に構成しています。

ブログの編集や作成は「サーバー側のデータをそのまま扱う」場面が多いため、クライアント側で余計な状態やキャッシュを持たないようにし、常に最新の情報を見にいく形にしています。

・記事一覧

記事一覧では、D1から取得したデータをサーバーコンポーネントで直接描画しています。

Reactの状態をほとんど持たずに済むため、記事を更新した後にリロードしたり、手動でステートを管理したりする必要がありません。

・記事編集

編集画面では、URLのパラメータから記事IDを受け取り、サーバーコンポーネント側で該当記事を読み込みます。

編集フォームはシンプルな構成にしており、フォーム送信時にサーバーアクションを呼び出すだけで更新処理が完結します。

・記事作成(プレビュー付き)

新規作成画面にはプレビュー機能をつけています。

これは、入力しているタイトルや本文をそのまま別コンポーネントに渡して描画しているだけのシンプルな構成ですが、書いている内容をリアルタイムに確認できるため執筆体験がかなり良くなりました。

全体の設計意図

管理画面全体として、
・クライアント側には余計な状態を持たない
・必要なデータは都度サーバーで取得
・フォーム送信のロジックはすべてサーバーアクションに委譲
・画面遷移はApp Routerの仕組みで完結
・認証はCloudflare Accessで管理

という構成にすることで、小さくシンプルで壊れにくい管理画面に仕上げています。

完成したブログサイト

ここまで実装を進めて、最終的に今回のブログサイトは次のような形になりました。

Mosslog - Technical blog

全体として派手さはありませんが、日常的に記事を書いたり管理したりするうえでは十分な機能が揃ったシンプルな技術ブログになったと思います。

おわりに

アドベントカレンダーをきっかけに始めた今回のブログサイト作りですが、当初予定していたものより色々作り込むことになり、結果的にとても良い経験になりました。

まずは最低限の機能だけですが、実働が2週間くらいの割にはそこそこいいものができたと思います。

今後も少しずつ機能を追加していく予定です。
 
どこか一部でも参考になれば嬉しいです。ありがとうございました!

江藤皓史/FIXER
有明高専卒24入社
チョコミント/TRPG/まーちゃんごめんね

カテゴリートップへ

この連載の記事