← ブログ一覧
技術ブログ

CMS移行の手順ガイド ― コンテンツも画像も、CSV 1本で引っ越す

平原 典彦 — Tesseraを開発しているエンジニア。ヘッドレスCMSとAI連携に関心があります。

CMSの移行で本当に時間を食うのは、記事を移し替える作業そのものではありません。構造(コンテンツタイプとフィールド)を移行先で作り直すことと、画像を1枚ずつダウンロードしてアップロードし直すことです。この記事では、その2つをできるだけ自動に寄せた上で、Tesseraへ移行する手順を上から順に書きます。読みながらそのまま進められる構成にしています。

移行の流れは4ステップです。

  1. 棚卸し:何を、いくつ、どう参照し合っているかを書き出す
  2. 書き出し:いまのCMSからCSVを作る
  3. 取り込み:参照される側から順にCSVを入れる(画像はURLのまま)
  4. 確認と公開:下書きで入った内容を確認して公開する

ステップ1:棚卸し(30分)

移行前に、次の4点をメモに書き出します。ここを飛ばすと、取り込みの順番で必ず詰まります。

  • コンテンツの種類と件数:記事・お知らせ・著者・カテゴリ・タグなど。件数は概算でよい
  • 参照関係:「記事 → 著者」「記事 → カテゴリ」のように、どの種類がどの種類を指しているか。矢印のを先に取り込む必要があります
  • 画像の場所:本文中の画像か、アイキャッチのような専用フィールドか。専用フィールドの画像はURLのまま移せます(後述)
  • 本文の形式:HTMLかMarkdownか。TesseraのリッチテキストはMarkdownなので、HTMLなら変換が要ります

ステップ2:いまのCMSからCSVを書き出す

TesseraはCSVインポートに対応しています。CSVにする理由は、ほぼどのCMSからでも作れる形式だからです。書き出しの手段はCMSごとに違います。

  • 書き出し機能があるCMS:管理画面のエクスポートをそのまま使います。列の名前は後で読み替えられるので、そのままで構いません
  • APIしかないCMS:コンテンツAPIで一覧を取得してCSVにします。この変換はClaude CodeやCursorに「このJSONを、この列順のCSVにして」と頼むのが最短です(数分で終わります)。TesseraのMCPを接続していれば、「Tesseraのインポートに合うCSVにして」と頼むだけで、エージェントが仕様(get_csv_import_spec)を取得して変換します
  • WordPress:標準の書き出しはWXR(XML)です。CSVにするには書き出しプラグインを使うか、WXRをAIエージェントにCSVへ変換してもらいます。本文はHTMLなので、あわせてMarkdownへ変換します(turndownのようなライブラリでも、エージェントに頼んでも構いません)
  • Newt:2026年11月24日にサービスが終了します。APIから取得したJSONをCSVに整形する経路になります。終了日が近づくと駆け込みで混み合うので、早めに書き出しだけでも済ませておくのを勧めます

CSVの形式で守ることは3つだけです。

  • 1行目はヘッダー(列名)
  • 文字コードはUTF-8推奨。Shift_JISでも自動判定して読めます
  • 複数の値は1つのセルにまとめ、「;」または「|」で区切る(どちらでも可)

仕様の全文はCSVインポート仕様にまとめてあります。

例(記事のCSV):

title,body,author,category,coverImage,publishedAt
"はじめての移行","## 見出し
本文です。",山田 花子,お知らせ,https://old-cms.example.com/uploads/hero.jpg,2026-09-01

ポイントは、参照先はIDではなく名前で書くことと、画像はURLのまま書くことです。

ステップ3:参照される側から順に取り込む

3-1. 新しい種類として作る場合(スキーマの雛形を自動推論)

移行先にまだコンテンツの種類が無いなら、「移行」画面にCSVをアップロードします。Tesseraがヘッダーと値から各列の型を推論し、コンテンツの種類の雛形を作ります。

CSVスキーマ推論のプレビュー。画像URLだけの列が「media」として提案され、確信度と判定理由が表示されている

画像URLの列は、メディア型として提案される。取り込み時にURLから取得して自ワークスペースのアセットに保存する。

  • 日付らしい列は日付、true/falseの列は真偽値、少数の値を繰り返す列は選択肢
  • 画像・PDF・動画のURLだけの列は、メディア型として提案されます(区切りで複数枚なら複数メディア)
  • 参照(他の種類への矢印)だけは自動では選びません。列ごとに「参照」を選び、参照先の種類を指定します

内容を確認して「この内容で作成してインポートする」を押すと、種類の作成と取り込みが1回で終わります。やり直したいときは「元に戻す」で取り消せます。

3-2. 既存の種類に入れる場合

種類がすでにある(先に手で作った、または前回の取り込みで作った)なら、その種類の一覧画面を開き、右上の「…」→「CSVインポート」から入れます。ヘッダーは種類のシステム名(titlebody など)に合わせます。サンプルCSVをダウンロードすると、列名と書き方がそのまま分かります。

コンテンツ一覧のCSVインポート画面。参照は代表表示名、メディアは画像のURLか既存アセットのID、複数値は区切り文字で指定すると案内されている

既存の種類へのCSVインポート。既存のコンテンツは変更されず、常に新規として追加される。

3-3. 画像はURLのままでよい

メディア型の列に旧CMSの画像URLが入っていれば、取り込み時にTesseraがそのURLから画像を取得し、あなたのワークスペースのアセットとして保存して紐づけます。事前にダウンロードしてアップロードし直す必要はありません。これはCSVだけでなく、MCPやGraphQLでコンテンツを作るときも同じです。

  • 同じ画像を複数の記事で使っていても、取得は1回だけ
  • 対応形式は画像・PDF・動画(1ファイル20MBまで)。SVGは対象外
  • 取得できなかった行は「行番号+理由」で報告され、他の行の取り込みは止まりません

注意点が1つあります。本文(Markdown)の中に書かれた画像URLは、そのまま旧CMSを指しています。旧CMSを解約する前に、本文中の画像を移し替えてください。MCPを接続していれば、エージェントに「本文中の画像をTesseraに取り込んでURLを差し替えて」と頼めます(import_asset_from_url)。

3-4. 取り込む順番

参照される側 → 参照する側、の順で入れます。たとえば「著者」「カテゴリ」を先に、「記事」を後に。記事CSVの著者列に書いた名前は、先に入れた著者の名前と突き合わせて自動で紐づきます。

ステップ4:確認して公開する

取り込んだコンテンツは、すべて下書きとして入ります。公開中のサイトに突然出ることはありません。一覧の「下書き」タブで内容を確認し、チェックボックスで選んで「公開する」でまとめて公開します。

確認の観点は3つです。

  • 参照が正しく紐づいたか(記事の著者・カテゴリが「-」になっていないか)
  • 画像が表示されるか(編集画面の右側のパネル)
  • 日付と本文の見た目

詰まりやすいところ

  • 文字化け:UTF-8で保存し直すのが確実です。ExcelでCSVを保存するときは「CSV UTF-8」を選びます
  • 日付2026-09-01 のようなISO 8601形式にします。2026/9/1 は日付として読めません
  • 先頭ゼロ:郵便番号や商品コードは数値として推論されると先頭の0が消えます。プレビューで型を「テキスト」に変えてください
  • 重複:スラッグのような一意の項目が重複している行はエラーになります。行番号が出るので、CSV側を直して再実行します
  • 必須項目の空欄:その行だけスキップされます。他の行には影響しません

移行後にできること

移行が終わると、コンテンツはGraphQLで関連を含めて1リクエストで取れ、Claude CodeやCursorからMCPで直接操作できます。「記事にタグを追加したい」と伝えれば構造の変更案が出てくる、という体験は移行後に試してみてください。

移行ガイド(機能の詳細)CSVインポート仕様無料で始めるドキュメント

CMS移行の手順ガイド ― コンテンツも画像も、CSV 1本で引っ越す | Tessera