長いことWordPressで運営していたこのサイトを、2026年5月にSanity+Astroの構成へ移行しました。公開先はCloudflare Pagesです。

WordPressに致命的な不満があった、というわけではありません。普通に記事を書いて公開するだけなら十分便利ですし、Cocoonのような無料テーマでも一通りの機能は揃います。

ただ、運用を続けていると、プラグインの更新、バックアップ、セキュリティ対策、変なアクセスをブロックしたという通知などが少しずつ負担になってきました。サイト自体もやや重く、デザインやページ構造を細かく調整しようとすると、テーマの仕組みを追いかける必要があります。

色々あって、個人サイトを昔ながらのホームページのような形にしてみよう[1]と思い立ちました。作業していると、WordPress上で自分のイメージを形にするのは結構難しいことに気づきます。凝った固定ページを作るなら、いっそソースコードを直接書いた方が楽なのではないか。画像がめちゃくちゃでどうなってるかわからないし、カスタムしたPHPとかどこにどう書いたかなんて覚えてない。サイト全体を、自分で把握できるシンプルな状態に戻したい。昔の、HTMLファイルを作ってFTPでアップロードしていたホームページのように、中身と公開の流れが見える構成にしたい。

そんなことを考えたのが移行の始まりでした。

この記事では、技術選定からWordPress記事の移行、URL設計、公開先の切替、メールサーバーの移行まで、実際にやったことをまとめます。個人サイトを移行するときに何を決め、どこに注意したかの記録です。

移行の第一目的|保守負担とセキュリティ対策を軽くする

サイトを作り直すにあたっての第一目的は、WordPressの保守負担とセキュリティ対策を軽くすることです。そのうえで、活動全体の情報を一か所にまとめ、自分でもコンテンツの状態を把握しやすくしたいと考えていました。

WordPressでは、記事も固定ページも、どうしてもテーマやプラグインの作法に影響されます。このサイトには、通常の記事のほかに、作品や実験的なプロジェクト、シリーズ、外部サービスで公開したコンテンツをつなぐログなどがあります。それらをすべて「ブログの中の何か」として扱うより、それぞれを管理しやすい形で置いておきたいと思いました。

そこで、コンテンツの管理と、Webページとしての表示を分離する、流行りのナウい仕組み、Headless CMS構成を試すことにしました。

最終的な構成

移行後の大まかな構成は次の通りです。

text
Sanity(記事、画像、分類の管理)
        ↓ GROQでビルド時に取得
Astro(固定ページ系は直接記述し、記事系はSanityから静的ページを生成)
        ↓ 静的HTMLを出力
Cloudflare Pages(公開、独自ドメイン、リダイレクト)

コードはGitHubで管理し、masterブランチの更新をCloudflare Pagesへ反映します。問い合わせフォームはFormspree、メールはさくらのメールボックスへ分離しました。

公開中のサイトは基本的に静的HTMLです。閲覧者がページを開くたびにWordPressやデータベースが動く構成ではありません。自分が求めていた「中身がシンプルで、表示が軽く、攻撃対象を減らしやすいサイト」に近い形です。

microCMSとSanityを比較して、Sanityを選んだ

Headless CMSの候補として、最初はmicroCMSとSanityを比較しました。

microCMSは日本語UIで、国内向けの情報も多く、初めて使うには分かりやすそうでした。一方、Sanityはスキーマの自由度が高く、Portable Textを使って本文を構造化できます。管理画面そのものもコードで調整できます。

最終的にSanityを選んだ一番大きな理由は、個人サイトなら無料枠で十分運用できそうだったことです。開発難度はやや高そうでしたが、「まぁ、どうにかなるだろう」という見切り発車でした。

管理画面が英語であることも、特に大きな問題とは考えませんでした。AIのサポートもありますし、英語の勉強にもなるだろう、くらいの感覚です。

実際に使い始めると、記事用のlog、固定ページ用のpage、カテゴリ、タグ、シリーズ、プロジェクト、掲載プラットフォームなどを、それぞれ独立したデータとして作れる点が便利でした。既成のブログ構造に自分のコンテンツを合わせるのではなく、サイトに必要な構造を比較的自由にこちらで決めることができます。

Astroを選んだのは、静的サイトにしたかったから

Movable Typeや初期のWordPressあたりの知識で止まっていたので、最近のWebサイト構築がどうなっているのか試してみたかった、という技術的な興味もありました。ただし、Astroを選んだ理由としては、実用面の方が大きいです。

記事中心のサイトなら、毎回サーバーでページを組み立てなくても、あらかじめ静的HTMLを作って配信できます。静的サイトは軽く、公開側の構成が単純で、WordPressに比べるとセキュリティ上気にする範囲はかなり小さくできます。

Sanity、Astro、移行スクリプトは、JavaScript/TypeScriptとNode.jsの周辺でまとめられました。WordPress XMLの変換、Sanityのスキーマ、Astroのコンポーネントまで、同じエコシステム内でつなげられます。

公開用ビルドは静的HTMLにしつつ、必要なときだけローカルでSanityのプレビュー機能を使う構成にもできました。

WordPressの投稿を整理してもってくる

今回の移行では、WordPressの記事を別のCMSへ丸ごとコピーするだけではなく、データ構造を整理し直しました。
Sanityでは、通常の記事をlog、固定ページをpageとして分離しました。(後で固定ページはAstro直管理に変更しました。※下の「補足:固定ページは、途中でAstroへ移した」参照)

分類も、WordPress標準のカテゴリとタグだけではなく、カスタムタクソノミーで登録していたものも整理して独立したデータにしています。

text
log
├── category
├── tags[]
├── series[]
├── projects[]
└── platforms[]

ひとつ記事が特定のプロジェクトに属し、シリーズの一部でもあり、どのプラットフォームに関係しているか、といった状態を参照として持てます。

WordPressのカスタムタクソノミーでも同じような構造は作れますが、それよりはシンプルで、消そうが修正しようが影響が少ない点も良いです。

補足:固定ページは、途中でAstroへ移した

移行初期には、通常の記事をlog、固定ページをpageとして、どちらもSanityで管理する設計にしていました。しかし作業を進めるうちに、AboutやProjectsのような固定ページは、記事と同じ形式で本文だけを管理するより、ページの構成や見せ方まで含めてAstro側で直接編集した方が扱いやすいと感じました。

そこで、Sanityに入っていた固定ページの本文をいったんHTMLへ変換し、about-this-site.astroprojects.astroなどのAstroファイルとして書き出しました。同時に、Sanityのpageを読み込んで動的に固定ページを生成していた処理も外し、Sanityから生成するページは主にlog記事と分類ページへ絞りました。

現在のAboutやProjectsなどは、Astroファイルの中にHTMLに近い形で本文やレイアウトを直接書いています。更新時にはGitHub経由のビルドとデプロイが必要ですが、記事のように頻繁に更新するページではないため、大きな不便はありません。むしろページ全体をソースコードとして見渡せるようになり、最初に考えていた「昔ながらのホームページに近い管理」へ一歩戻った形になりました。

WordPress XMLをSanity用のデータへ変換する

WordPressからはXMLでデータを書き出し、Node.jsのスクリプトでSanityへ読み込めるNDJSONへ変換しました。

大まかな流れは次の通りです。

  1. WordPressから記事と分類データをエクスポートする
  2. XMLから投稿、固定ページ、カテゴリなどを取り出す
  3. 本文HTMLをPortable Text、画像、HTML埋め込みなどへ変換する
  4. 記事と分類をSanityのReferenceで結ぶ
  5. NDJSONを生成する
  6. Sanityのproduction datasetをバックアップしてからインポートする
  7. 件数と代表記事の表示を確認する

移行対象になった公開投稿は167件でした。メイン画像166件、本文画像499件、画像URLは625件あり、最終的に未解決画像は0件になりました。このほか、Moshimoの埋め込み115件、テーブル20件などもありました。

表示の細かいチェックはせず、変換ルールを作り、まとめて処理し、問題のありそうな部分を確認するだけにしました。過去記事のチェックをしていたらかなり時間がかかってしまうので、それは流れで追々やる感じで。

WordPress固有の表現は、全部きれいにしようとしない

幸い、元のサイトではWordPressテーマ固有のブロックやショートコードを大量には使っていませんでした。そのため、まずは情報として読めるシンプルな形へ移すことを優先しました。

全記事を一つずつ細かくチェックするのではなく、主要な記事や、特殊なブロックを使っていた記事を重点的に確認しました。それ以外は、多少表示が簡素になっても、本文が読めて画像やリンクが機能していれば、とりあえずそのままにしています。

通常の本文はPortable Textへ変換し、画像はSanityのassetとして扱いました。アフィリエイトや表組みなど、構造化しにくいものはhtmlEmbedとして分離しました。特定記事だけのHTMLは残せるようにしつつ、scriptやイベント属性は除去しています。

すべてを完璧なPortable Textへ変換しようとすると、記事固有の表現を落とす可能性があります。逆に、WordPressのHTMLを無条件で残すと、テーマ依存や不要なコードまで持ち込むことになります。

「構造化するもの」「限定的にHTMLで残すもの」「削除するもの」を分けることが重要でした。

記事URLはできるだけ変えない

個別記事は、旧WordPressのときと同じ/{slug}/を維持しました。記事一覧や分類ページは/nonfiction/の下へ整理しましたが、旧URLから新URLへリダイレクトを設定しています。

text
/category/tools/  →  /nonfiction/category/tools/
/blog/            →  /nonfiction/
/feed/            →  /rss.xml

ルーティング変更だけでなく、リダイレクト、canonical、OG URL、内部リンク、XML sitemapをまとめて更新しました。日本語slugやパーセントエンコードされたURLも確認対象です。

既存の検索結果、外部リンク、ブックマークをできるだけ壊さないことを優先しました。

公開先はCloudflare Pages

公開先にはCloudflare Pagesを選びました。これも、個人サイトなら無料枠で十分そうだったことが大きな理由です。仮に将来有料化が必要になっても、小規模向けの選択肢がありました。

Astroが生成したdistをそのまま公開でき、GitHubとの連携、プレビューデプロイ、独自ドメイン、エッジ側のリダイレクトも利用できます。

いきなり本番ドメインを切り替えるのではなく、まずpages.devのプレビューURLへデプロイしました。トップ、記事、固定ページ、RSS、robots.txt、sitemap、リダイレクト、問い合わせフォームを確認してから、oneoffobject.comwww.oneoffobject.comを接続しています。

Webより面倒だったメールサーバーの移行

複雑だったのはWebサイトよりメールです。

移行前のColorfulBoxでは、Webサーバーとメールサーバーを同じドメイン周辺で管理していました。さらに、PODショップ側のドメインのメールもColorfulBoxを使っていたため、Webだけを先に切り替えてメール用DNSを壊すわけにはいきません。

そこで、Webサイトの本番切替とは別に、メールを先にさくらのメールボックスへ移しました。選んだ理由は、これも安かったからです。費用は年1,000円程度でした。

MX、SPF、DKIM、DMARC、Search Console確認用のTXTレコードを整理し、メールの送受信を確認してから、Cloudflare側へWebのDNSを切り替えました。

時系列にすると、だいたい次の流れです。

text
5月4日   移行の検討を開始
5月12日  メールをさくらへ切替、送受信確認
5月13日  Cloudflare Pagesへ本番ドメインを切替
5月17日  移行プロジェクトを完了扱い、WordPressを非公開化
5月20日頃まで  細部の確認・調整

「ビルド成功」からの確認

Astroのnpm run buildが成功しても、それだけでは安心できません。

生成されたdist内のHTMLを確認し、代表的な記事、固定ページ、分類ページ、プロジェクトページを開きました。RSS、robots.txt、XML sitemap、canonical、旧URLからのリダイレクトも確認しています。

問い合わせフォームは、実際に送信し、完了ページへ移動すること、通知メールが届くこと、Reply-Toが入力者のメールアドレスになることまで試しました。DNS切替後には、Webとメールの両方をもう一度確認しました。

Sanityで記事をPublishしても、公開中の静的HTMLがその場で直接書き換わるわけではありませんが、このサイトではSanityのWebhookからCloudflare PagesのDeploy Hookを呼ぶ設定にしているため、PublishをきっかけにCloudflare Pagesが自動で再ビルドとデプロイを行います。通常はPublish後に数分待てば本番環境へ反映されるので、手動でビルドする必要はありません。なので、更新したい時はローカル環境でPublishするだけという手軽さです。

実際の費用と期間

移行の検討を始めたのは5月4日で、主要な切替は5月13日、プロジェクトとしては5月17日に完了扱いにしました。その後も細部を調整しており、5月20日頃にはだいたい落ち着いていたようです。

新たにかかった固定費は、さくらのメールボックスの年1,000円程度です。SanityとCloudflare Pagesは、現状では無料枠内で運用しています。

2026年8月時点で、Sanityの無料枠には10,000件のドキュメント、100GBのアセット保存容量、月250,000回のAPIリクエスト、月100GBのデータ転送量などが含まれています。Cloudflare Pagesも、静的ページへのアクセス数と帯域幅は無料プランでも無制限で、ビルドは月500回までです。現在のこのサイトは、Sanity上のドキュメントが約200件、アセットが約126MBで、API使用量も月間上限の1割未満に収まっています。一日一記事を更新する程度の個人サイトなら、どちらも無料枠にはかなり余裕があります。将来有料化する場合は、Sanityが1人運用で月15ドルから、Cloudflare Pagesのビルド上限を増やすProプランが月20ドル相当からです。

まぁ、このサイトでは課金が必要になることはまず無さそうです。
ということはよほどの仕様変更でも無い限り、ドメイン代だけでサイトを運用し続けられます。零細個人事業主にとって、これは非常に嬉しいです。

タイミング悪く、ColorfulBoxは3月頃に更新料を支払ったばかりだったため、すぐには解約していません。今解約しても差額返金は無いし……。使う予定はないけどとりあえず残しておいて、次回更新前に解約する予定です。そうすれば今後Webサーバー代は不要です。やったね。

スペシャルサンクス:Codex

今回の移行ではCodexに活躍してもらいました。XML変換、コード修正、確認項目の整理など、作業量の多い部分ではかなり助かりました。

とはいえ、AIに丸投げすれば全部終わる、という感じではありませんでした。ある程度は人間側にも知識がないと、何が問題なのか分からず、指示も出しにくくなります。表示はできていてもURLやメールが壊れている、ということもあり得ます。

細部を気にしなければ丸投げでもある程度形になりそうですが、作業を進めるほど、canonical、リダイレクト、埋め込み、管理画面の使い勝手、微妙なフォントサイズ、マージンなどが気になってきました。最終的な判断と確認は、人間側に残しておく必要があります。

移行後の記事更新

Sanity Studioでの記事作成は、最初こそ少し戸惑いましたが、すぐに慣れました。

移行後は、記事作成画面のバグを直したり、入力UIをカスタマイズしたりする手間は発生していますが、それでもWordPressの頃の管理の手間と比べたら大したことはありません。

現在はObsidianなどで書いたMarkdownをそのまま貼り付ければ、見出し、リスト、脚注、calloutなどをPortable Textへ変換できるようなっています。楽です。

まとめ

今回の移行は、WordPressをSanityへ置き換えるだけで済むだろうと甘い考えでしたが、そう簡単ではありませんでした。これまでWordPressに適当に入れていた情報や、レンタルサーバーがまとめて引き受けていた役割を、一つずつ確認して分離する作業は大変でした。

ですが、やってよかったです。
Headless CMS関係を触ってみて、無駄に細かいことを気にする人間にとって、この自由度の高さは良かったです。自由度が高すぎると、他にも機能を実装してみたくなるのが難点ですが……。
静的サイトにしたことで、公開側は軽く単純になったし、バックエンドも、自分の運用に合わせて改善しやすいので、WordPressの頃より更新のハードルはだいぶ下がりました。

以上、WordPressからSanity+Astroへ個人サイトを作り直した記録、でした。


  1. GEO対策をしてみようと思い立って、ちょっとWordPressの中身を整理したときの記録 GEO時代のほめぱげ — GEO対策にブログをホームページ化してみる|OneOffObject

    本文に戻る

DID YOU ENJOY THIS ARTICLE?

制作活動を支援する / Support my work

文章、アート、デザイン、個人開発を続けるための支援を、コーヒー一杯分から受け付けています。 / Help me keep making essays, art, design, and independent software.

Buy Me a Coffee

情報 / Information

Title
WordPressからSanity+Astroへ — 個人サイトを作り直した記録
Published
2026/08/11