これまでClaude Codeを利用して、Claude Codeに推奨された方法でブログを作成してきました。作り始めて2週間は、試行錯誤しながら夢中で運用してきたのですが、1日1記事ペースでアップするようなルーティンができてきたため、現状のブログ運用の仕組みを整理したくなりました。

Claude Codeにこんなことやりたい、あんなことやりたいと相談して、今の仕組みが出来上がりました。その中で、何回もClaude Codeが思ったように動いてくれないこともあり、一度、「仕組みが悪いんじゃないか。全体の仕組みを見直して。」とお願いしたこともあります。このように、Claude Codeに仕組み構築をお願いしていたこともあり、自身でも全体像がどのようになっているのかをぼんやりとしかわかっておらず、今回それをClaude Codeに整理してもらいました。

整理していく中で、以下のような課題が今の仕組みで対処されていることが改めてわかりました。

  • 記事を書いてすぐ公開するのは怖い。確認してからアップしたい
  • 外出先からでも記事の内容を確認したい
  • 「毎朝8時に投稿」みたいな予約投稿が静的サイトでできるか分からない

結論から言うと、Draft環境と本番環境を分けた2段階フローを持つことで、これらの課題をすべて解決しています。 ファイルの置き場所だけで公開先が変わるシンプルな仕組みなので、一度作ってしまえば運用はほぼ自動です。

なぜこのフローで十分なのか。それは、GitとCloudflare Pagesの組み合わせが「ファイルを動かす=公開状態を変える」という単純な構造で動いているからです。本記事では、このブログ「金融エンジニアの資産運用実験室」で実際に運用している仕組みをベースに確認していきます。

※本記事は個人の運用体験をもとにした仕組み紹介です。構成の詳細は環境によって異なります。


この記事でわかること

  • このブログが採用している2段階公開フローの全体像
  • Draft環境をGoogle検索からブロックしている理由と方法
  • frontmatterの公開日時フィールドとGitHub Actionsを組み合わせた予約投稿の仕組み
  • Claude Codeとの組み合わせで回るサイクル

まず全体像を把握しておきましょう。このブログでは以下の3ステップで記事を公開しています。

Draft→本番の2段階公開フロー

左:記事を書いてアップロード 中:Draft環境で確認 右:確認OKで本番に公開

各ステップで登場するツール・サービスの名前に馴染みがない方も多いと思います。次のセクションで登場人物を整理してから、詳細の説明に入ります。


登場人物:ブログ運営に出てくるツール・サービス

この仕組みには、聞き慣れない名前がいくつか出てきます。本題に入る前に、それぞれの役割を簡単に整理しておきます。

登場人物の関係図:ローカルPC・GitHub・Cloudflare Pages

ローカルPCで記事を書き、GitHubへアップロード。GitHub上でHugoとGitHub Actionsが動き、Cloudflare Pagesへ送信してブログが公開される

ローカルPC

記事を書いたり編集したりする、手元の自分のパソコンのことです。「ローカル」とは「手元・自分の環境」という意味で、インターネット上のサービス(クラウド)と対比して使われます。このブログでは、Claude Codeを使った記事の執筆・修正はすべてローカルPCで行っています。

GitHub(ギットハブ)

クラウド上のファイル管理サービスです。Wordでいう「変更履歴の保存」を強化したもの、とイメージしてもらうと近いです。「いつ・誰が・何を変えたか」を記録しながらファイルを管理でき、変更をアップロードする操作を「push(プッシュ)」と呼びます。このブログの記事ファイルはすべてGitHubで管理しています。

Cloudflare Pages(クラウドフレア ページズ)

Cloudflareは、Webサイトの高速配信やセキュリティ対策を提供する世界規模のインターネットインフラ企業です。その中の「Pages」というサービスが、Webサイトのファイルを受け取ってインターネット上に公開・配信する機能を担っています。皆さんがブラウザで見ているこのブログは、Cloudflare Pages上に置かれています。このブログはDraft(確認用)と本番の2環境をCloudflare Pages上に持っています。

Hugo(ヒューゴ)

Markdownという書きやすい形式で書いた記事ファイルを、ブラウザで見られるHTML形式に変換するソフトです。「記事を書く作業」と「Webサイトとして見せる作業」を分けてくれる変換エンジンです。このブログでは、HugoはCloudflare上ではなく、GitHub Actions(GitHubのサーバー)上で動いています。

GitHub Actions(ギットハブ アクションズ)

GitHub上で動く自動化機能です。「毎時0分になったら○○の処理を実行する」「ファイルが更新されたら○○する」といった条件付き・定時実行の仕組みを設定できます。この定時実行の仕組みのことを特に cron(クロン) と呼びます。このブログの予約投稿機能はGitHub ActionsのCron機能で動いています。

Claude Code(クロード コード)

AnthropicのAI「Claude」をターミナル(コマンド操作画面)から使えるツールです。記事の執筆・修正はもちろん、GitHub Actionsのワークフロー設定ファイルのような技術的な実装もClaude Codeに依頼しながら作ってきました。このブログ運営の実質的な共同作業者です。

このブログの記事は、Claude Codeにベースとなる下書きを作成してもらい、そこに私自身の経験や知見をClaude Codeと対話しながら追加・修正してもらう形で作成しています。


記事が公開されるまでの基本の流れ

Draft環境の話に入る前に、まず「ブログ記事がどういう流れで公開されるのか」という基本から整理します。

① 記事ファイルの作成(ローカルPC上)

記事の執筆はClaude Codeで始めます。執筆の起点は2パターンあります。

  • ニュースから探すパターン:Claude Codeにブログの趣旨に合うニュースや話題を探してもらい、その中から筆者がテーマを選んで執筆を依頼する
  • テーマ先行パターン:筆者がテーマを思いついたとき、記事の大まかな流れをClaude Codeに説明して書いてもらう

どちらのパターンも、ブログ記事の最初の執筆はClaude Codeが担当しています。その後、筆者が自身の経験や知見を加えながらClaude Codeと対話して仕上げていきます。

そうして作成した記事は、Markdown形式(.mdファイル)としてローカルPC上に保存されます。ファイルの先頭には frontmatter(フロントマター)という設定ブロックがあり、タイトル・公開日・公開状態などを記述します。

---
title: "記事のタイトル"
date: 2026-05-01T08:00:00+09:00
draft: false
---

記事ファイルの公開状態(ステータス)は実質2つです。

状態 設定 動き
下書き draft: true GitHubにアップロードしても本番サイトには出ない
公開対象 draft: false アップロードすれば本番サイトに反映される

date: フィールドで公開日時を指定することもできます。これを使った予約投稿の仕組みについては後半で解説します。

② ローカル確認 → GitHubへアップロード

記事ファイルはテキスト形式のため、そのまま開いてもブログとして公開されたときのレイアウトでは表示されません。そこで、ローカルPC上にHugo用の小さなサーバーを立ち上げ、ブラウザ経由でアクセスすることで、公開後に近い見た目で記事を確認することができます。難しそうに聞こえますが、Claude Codeに「ローカルで確認したい」と伝えるだけで自動的にやってくれます。問題がなければGitHubへアップロードします。

ただし、このローカルサーバーはPCが起動している間だけ、自分のPCからしか参照できません。外出先やスマホから同じURLにアクセスしても見ることはできません。

③ GitHub Actionsが起動 → 変換・公開 → ブログに反映

GitHubへアップロードすると、GitHub Actionsが変更を検知して起動します。GitHub Actionsのサーバー上でHugoがMarkdownをHTML(Webページ)に変換する処理を実行し、完成したHTMLファイルをCloudflare Pagesへ送信します。Cloudflare PagesがそのHTMLを受け取って配信することで、数十秒後には本番ブログに反映されます。この③の流れはすべて自動で、手動の操作は不要です。

ただし、Hugoのデフォルトの動作では、公開日時が未来の記事は除外されます。 記事を公開するには、公開日時をアップロード時点より過去の時間に設定するか、この除外動作を変える仕組みを別途用意するかのどちらかが必要です。このブログでの具体的な解決方法は、後半の「公開日時の予約投稿はどう実現しているか」で詳しく解説します。

人から見ると、記事が現れるのは③のタイミング

①②はいずれも筆者の手元での作業です。記事を書いてアップロードするまでの過程は読者には見えません。読者がブログを訪れて記事を目にするのは、③のCloudflareによる公開が完了したタイミングです。

基本の流れでは、②でアップロードすると③が自動で動き出し、そのまま本番に公開されます。つまりアップロードと公開はほぼ同時です。確認の間もなく公開されてしまうため、この③をより安全に運用するために設けたのが、次に説明するDraft環境を使った2段階フローです。

💡 コラム:Claude Codeがよく使う3つの言葉 — push・ビルド・デプロイ

Claude Codeと対話しながら作業していると、この3つの言葉が頻繁に出てきます。それぞれ①〜③のどこにあたるかを整理しておきます。

用語 読み方 どこの作業か 具体的な内容
push プッシュ ローカルPCで編集したファイルをGitHubへアップロードする操作
ビルド ビルド ③前半 HugoがMarkdownファイルをHTMLに変換する処理。pushを検知したGitHub Actionsが自動実行する
デプロイ デプロイ ③後半 ビルド済みのHTMLをCloudflare Pagesに配置して公開する処理。ビルド完了後にGitHub Actionsが自動実行する

「アップロードしたらビルドが走り、完了したらデプロイされる」という順番です。③の「数十秒後に反映」の中身は、実はビルドとデプロイの2ステップで構成されています。

push・ビルド・デプロイの流れ:ローカルPC→GitHub→HTML→Cloudflare Pages

ローカルPCからアップロード(push)→GitHubがビルド(変換)→Cloudflare Pagesにデプロイ(公開)の順で自動実行される


このブログの構成:Draft環境と本番環境を分けた2段階フロー

Draft→本番の2段階公開フロー

左:記事を書いてアップロード 中:Draft環境で確認 右:確認OKで本番に公開

このブログは「Draft環境」と「本番環境」の2つの環境で動いています。ここで言う「環境」とは、それぞれ独立したウェブサイトのことです。Cloudflare Pages 上に2つのサイトが存在していて、役割が異なります。

一方、「フォルダ」は GitHub 上のファイルの置き場のことです。この2つは別の場所にある別の話ですが、「どのフォルダに置くか」が「どの環境に出るか」を決めるという形で連動しています。

GitHubのフォルダとCloudflare Pagesの環境の対応図

左のフォルダ(GitHub)と右の環境(Cloudflare)は別の場所にある。GitHub Actionsがアップロードのたびに両方を自動で変換・Web公開する

整理すると、次のようになります。

場所 名前 役割
GitHub(ファイル管理) 確認用フォルダ 確認中の記事を置く
GitHub(ファイル管理) 公開用フォルダ 本番に出す記事を置く
Cloudflare Pages(ウェブサイト) Draft環境 確認用・URL限定公開
Cloudflare Pages(ウェブサイト) 本番環境 誰でも閲覧できる公開サイト
  • 確認用フォルダに置いた記事 → Draft環境にだけ表示される
  • 公開用フォルダに置いた記事 → 本番環境に表示される

本番アップしたいときは、確認用フォルダから公開用フォルダへ記事を移動するだけです。移動後にアップロードすれば、あとはGitHub Actionsが自動で変換・Web公開します。コピーではなく「移動」なので、同期ずれが起きません。


なぜDraft環境を用意したのか

ローカルサーバーの立ち上げが手間・外出先から確認できない

記事ファイルを作成したあと、ローカルで確認するにはHugoのサーバーをコマンドで起動する必要があります。毎回この手間がかかるほか、起動中も自分のPCからしかアクセスできません。「電車の中でスマホから確認したい」「外出先で最終チェックしたい」といった場面には対応できませんでした。Draft環境はURLが固定されているため、どこからでもスマホブラウザで確認できます。

ローカルでの確認には限界がある

ローカルPC上のサーバーでは、Cloudflare Pages固有の設定は再現されません。

たとえばOGP(SNSでシェアされたときのサムネイル・タイトル表示)はローカルでは確認できません。OGPはCloudflare Pages上に公開されたURLに対してSNSがアクセスして読み取る仕組みのため、ローカルサーバーのURLでは情報が取得できないからです。記事をXでシェアしたときにサムネイルが表示されない・タイトルがおかしい、といったトラブルはDraft環境で事前に防ぐことができます。「ローカルでは正しく見えていたのに、本番アップしたら壊れていた」を防ぐためにも、本番に近い環境での確認は重要です。


Draft環境はGoogle検索に引っかからない

Draft環境はURLを知っていれば誰でも見られますが、Google検索には出てきません。

仕組みはシンプルで、Draft環境(Cloudflare 上の確認用サイト)全体の robots.txt に以下を設定しています。

User-agent: *
Disallow: /

これはGoogleなどの検索エンジンのクローラー(自動巡回プログラム)に対して「このサイト全体を読み込まないでください」と伝える記述です。この指示に従ったクローラーはページをインデックス(検索データベースへ登録)しません。なお、robots.txtはあくまでクローラーへの「お願い」であり、Googleのような主要な検索エンジンは尊重しますが、悪意ある第三者のプログラムには効かない場合もあります。URLを知らなければアクセスできないという意味では非公開ですが、完全な非公開とは異なります。

この robots.txt は GitHub のフォルダに置いているファイルではなく、Web公開処理が行われるたびに GitHub Actions が自動生成して Draft 環境のサイト全体に適用するものです。確認用フォルダ・公開用フォルダという「フォルダ単位」の制御ではなく、Draft環境という「サイト丸ごと」が Google 検索対象外になっています。

実際の設定はClaude Codeに「DraftサイトはGoogleに検索されないようにして」と伝えるだけで実装してもらいました。仕組みの中身を知らなくても、やりたいことを言葉で伝えればClaude Codeが適切な設定を選んでくれます。

なぜこれが必要かというと、「本番より先にDraftの内容がGoogle検索に出てしまう」リスクを防ぐためです。

同じ内容のページが2つのURLに存在すると、Googleから重複コンテンツとみなされてSEO評価に悪影響が出る場合があります。また、確認中の未完成の状態が外部に漏れることも避けたい。robots.txt での制御はそのための最低限の対策です。


公開日時の予約投稿はどう実現しているか

静的サイトには、ブログサービス(はてなブログ、noteなど)のような「予約投稿」機能がありません。代わりに、frontmatterの公開日時フィールドとGitHub Actionsのcron機能を組み合わせて予約投稿を実現しています。

frontmatterの公開日時で「いつ公開するか」を指定する

ブログ記事のMarkdownファイルの先頭には、frontmatterという設定ブロックがあります。

---
title: "記事タイトル"
date: 2026-05-01T08:00:00+09:00
---

Hugoはこの date フィールドを「記事の公開日時」として扱います。

  • 公開日時が現在時刻より過去の場合:通常通り本番アップの対象になる
  • 公開日時が現在時刻より未来の場合:Hugoが変換する際に除外され、本番アップの対象にならない

つまり date: 2026-05-01T08:00:00+09:00 と書いておけば、5月1日8時になるまでは公開されません。

予約投稿の仕組み:dateと現在時刻の関係、cronの自動チェックフロー

公開日時が現在時刻より未来なら非公開、過去になったらcronが自動で公開用フォルダへ移動して本番公開する

GitHub ActionsのCronが1時間ごとに自動チェック

「公開日時が過去になったら自動で本番アップする」処理を、GitHub Actionsのcron機能で動かしています。

GitHubには「定時に処理を実行する」スケジュール実行機能があり、これをcronと呼びます。設定は以下のような記述で行います(これはYAML形式のワークフローファイルです)。

on:
  schedule:
    - cron: '0 * * * *'  # 毎時0分に実行

このワークフローが1時間に1回、以下の処理を自動で行います。

  1. GitHub内の確認用フォルダの記事を全件チェック
  2. 公開日時が現在時刻より過去になった記事を検知
  3. 該当記事をGitHub内の公開用フォルダへ移動
  4. 移動した変更をGitHubの記録に保存
  5. GitHubの記録に基づき、記事ファイルをHTML変換してCloudflare Pagesに配置
  6. Cloudflare Pagesが配置されたHTMLを配信し、記事が本番に公開される

「毎朝8時に公開」と設定しておけば、最大で8時59分までには自動で本番に上がります。 cronは毎時0分に動くため、8時00分のチェックをわずかに過ぎてしまった場合、次のチェックは9時00分になります。このため最大59分のずれが生じますが、個人ブログの運用では十分な精度です。

なぜこの仕組みにしたか

もともと、記事を書き終えてから内容を確認して本番アップするまでに時間差があるため、本番アップのタイミングで公開日時を設定し直すようにしていました。ところが、操作のタイミングによっては「現在より少し未来の日時」が入ってしまい、本番アップしたはずの記事が表示されないという失敗を何度か繰り返してしまいました。

この失敗をなくしたいこと、そして今後は「毎週火曜に更新」のような定期的な投稿もしてみたいという考えもあり、Claude Codeに相談しました。その結果として提案・設定してもらったのが、この予約投稿の仕組みです。


Claude Codeとの組み合わせ

記事執筆・修正はClaude Codeで行うことが多く、このDraft→本番フローとの相性がよいと感じています。

実際のサイクルは以下のような流れです。

  1. Claude Codeに記事の下書きを作成・修正してもらう
  2. GitHubにアップロードしてDraft環境に反映させる
  3. Draft環境のページにアクセスして確認する
  4. 気になる点をClaude Codeに伝えて修正してもらう
  5. 再アップロードしてDraft環境で確認。問題なければ確認用フォルダから公開用フォルダへ移動して本番公開

静的サイトを選ぶと「自由に設定できる反面、仕組みを自分で作る必要がある」という面があります。その部分をClaude Codeが補ってくれることで、エンジニアでなくても自分専用の運用フローを作れるようになっています。


まとめ

このブログの公開フローを整理すると、以下のようになります。

  • GitHubへのアップロードで、Draft環境と本番環境の両方が自動で変換・Web公開される
  • 確認用フォルダに置いた記事はDraft環境に表示され、公開用フォルダに置いた記事が本番に表示される
  • Draft環境はサイト全体がGoogle検索の対象外に設定されている
  • frontmatterの公開日時を未来日時にすることで予約投稿を実現できる
  • GitHub Actionsが1時間ごとにチェックし、公開日時が過去になった記事を自動で公開用フォルダへ移動・本番公開する

「書いたらすぐ公開」ではなく「確認してから公開」できる安心感は、継続的なブログ運営にとって思っていた以上に重要でした。

まずはDraft環境を作るところから試してみると、自分のブログ運営に合った公開フローが見えてくると思います。何かの参考になれば幸いです。

同じ構成を作りたい方は、Claude Codeに「①HugoとCloudflare Pagesで静的ブログを作り、②Draft確認用と本番の2環境を用意し、③GitHub ActionsのCronで予約投稿できるようにしたい」と伝えると、同様の仕組みが実現できます。