「実績ページに『担当範囲』の欄を足したい」「この項目はもう使わないので消してください」。納品して数か月たつと、こうした依頼が届きます。WordPressならカスタムフィールドのプラグインで済む話に見えますが、ヘッドレスCMSでは同じ一言でも、戻せる操作と戻せない操作がはっきり分かれます。

このサイトのCMS(EmDash 0.32)の実装と管理画面を確かめた結論は3つ。足すのは安全、名前と型は基本的に変えない、消すのだけは戻せない。依頼を受けたときの段取りを、実際の画面と一緒に書いていきます。

項目の定義はコードではなく本番のデータベースにある

EmDashでは、入力項目の定義が記事と同じデータベースに入っていて、変更はデプロイ無しでその場で反映されます。ここを押さえておくと、以降の戻せる・戻せないの話がすっきりします。

管理画面の「コンテンツタイプ」で足す・直す

項目を触る場所は、管理画面の「コンテンツタイプ」です。コレクション(記事の種類)を開くと、右側に今ある項目の一覧と「フィールドを追加」ボタンが並びます。

EmDashの管理画面「コンテンツタイプ」でPagesを開いた画面。右側にシステム項目とカスタム項目の一覧、右上に「フィールドを追加」ボタン
管理画面「コンテンツタイプ」→ Pages。右側が項目の一覧(ローカル環境で撮影)

同じ操作はCLIの emdash schema add-field / remove-field でもできます。どちらも本番のAPIを叩くので、押した瞬間に本番の管理画面とサイトの両方に効きます。テスト環境で試してから本番、という流れを作るなら、作業する側が意識して分けておくことが欠かせません。

seedファイルを書き換えても本番は変わらない

開発の最初に作るseedファイル(項目定義と初期データをまとめたJSON)が効くのは、データベースが空の状態で起動した1回だけです。運用中のサイトに対してseedを書き換えてデプロイしても、項目は1つも増えません。公式ドキュメント「Evolve a deployed site's schema」にもそう書かれています。

「seedに足したのに管理画面に出てこない」という相談は、ほぼこれが原因です。

このサイトも納品後に12項目を足している

自分のサイトでも同じことをしています。Aboutページ用の項目は全部で14個。そのうち12個(経歴・お約束・スキルなど)は、コレクションを作った9日後に管理画面から足したものです。本番の項目定義に作成日時が残っているので、後から足したことがそのまま読み取れます。seedファイルは同じ日のコミットで揃えました。

足すのは安全。ただし「必須」で足すと既存記事は空で埋まる

項目を足しても、既存の記事が消えたり壊れたりすることはありません。気をつけるのは必須にして足したときだけです。

追加すると裏で何が起きているか

項目の追加は、データベースの記事テーブルに列を1本足す操作です。選べる型は16種類あり、ここで選んだ型があとで変えられるかどうかを決めます(次の節で詳しく書きます)。

「フィールドを追加」のダイアログ。短文テキスト、長文テキスト、数値、整数、ブール値、日時、選択、マルチセレクト、リッチテキスト、画像、ファイル、参照などの型が並ぶ
「フィールドを追加」で選べる型。ここで選んだ型は、あとから自由には変えられない

「必須」で足すと、既存の記事には何が入るか

列を足した時点で、既存の記事にもその項目の値が必要になり、必須の項目は空にできないのでEmDashは次の値で埋めます。

項目の型

既存の記事に入る値

短文・長文・選択・URL・日時など(文字列で保存する型)

空文字

整数・ブール値

0

数値(小数)

0.0

リッチテキスト・JSON・繰り返し・マルチセレクト

null

既定値を設定した場合

その既定値

問題は、空文字が入った状態で古い記事を直そうとしたときです。必須の入力チェックは保存のたびに走り、空文字は未入力として弾かれます。古い記事の誤字を1文字直したいだけの担当者が、見覚えのない項目のせいで保存できない、ということが起こり得ます。

安全に足す3ステップ

私は必須の項目を足すとき、次の順で進めています。

  1. まず任意の項目として追加する
  2. 既存の記事を埋める(件数が多ければAPIでまとめて)
  3. 全件埋まったのを確かめてから必須に切り替える

必須への切り替えは、項目定義の書き換えだけで済みます。テーブルには触らないので、後からでも安全にできます。

項目の名前(スラッグ)と型は、ほぼ変えられない

管理画面で変えられるのは表示名(ラベル)だけです。テンプレートが読むスラッグは、作成後に変更できません。

項目の編集ダイアログ。ラベル欄とスラッグ欄が並び、スラッグ欄の下に「フィールドスラッグは作成後に変更できません」と表示されている。型は「短文テキスト」の表示のみで選び直す欄はない
項目の編集画面。スラッグ欄の下に「作成後に変更できません」。型も選び直す欄が無い

更新APIの入力にもスラッグは含まれていないので、管理画面・API・CLIのどこからでも同じです。名前を変えたいときは、後で書く4手で作り直します。

型は「保存のしかた」が同じものどうしだけ変えられる

型はもう少し複雑です。管理画面の編集画面には型を選び直す欄がありません。APIからは変更を受け付けますが、通るのはデータベース上の保存形式が同じ型どうしだけです。

型の変更

通るか

理由

短文 → 長文・選択・URL

○

どれも文字列で保存

整数 ⇔ ブール値

○

どちらも整数で保存

リッチテキスト ⇔ JSON・繰り返し

○

どれもJSONで保存

短文 → 整数

×

文字列から整数に変わる

整数 → 数値(小数)

×

整数から小数に変わる

JSON → 短文

×

JSONから文字列に変わる

×の変更を送ると、FIELD_TYPE_COLUMN_CHANGE というエラーで止まります。メッセージの中身は「作り直すか、データを移してから変えてください」です。

通る変更も、値は変換されない

○の変更も、中に入っている値までは変換してくれません。このサイトのブログの日付 post_date は文字列型で、日時型に変えれば通りますが、入っている値は文字列のまま残ります。日時として正しく読めるかどうかは、変える前に全件を目で見て判断します。

名前を変えたいときの4手

スラッグを変えたいときは、次の4手で進めます。

  1. 新しい項目を足す(まずは任意の項目として)
  2. 古い項目から新しい項目へ値を写す
  3. テンプレートを新しい名前に切り替えてデプロイする
  4. 古い項目を消す
項目の名前を変えるときの4手。新しい項目を足す、値を写す、テンプレートを切り替えてデプロイ、古い項目を消す
名前を変えるときは「作り直し」。消すのは最後

4手目の「消す」だけが戻せない操作です。次の節の手順を済ませてから実行します。

削除だけは戻せない。消す前にやる3つ

項目を消すと、その項目に入っていた値が全記事から同時に消えます。元に戻す操作はありません。

項目の削除確認ダイアログ。「Delete Field? Are you sure you want to delete the 「ロール」 field?」とキャンセル・削除ボタンだけが表示されている
削除の確認画面。値まで消えるという警告は出ない

管理画面には確認画面が出ますが、文言は「この項目を削除してよいですか」だけです。値まで消えるとは書かれていません。

1. 戻れる地点を控える

Cloudflare D1なら、Time Travelという機能でデータベースを過去の時点に戻せます。消す直前に、今の時点を指すブックマークを記録しておきます。

# 今の時点を指すブックマークを表示する(消す直前に控えておく)
npx wrangler d1 time-travel info <データベース名>

ただし、Time Travelで戻すとデータベース全体がその時点に戻ります。削除の後に書いた記事や修正も一緒に巻き戻るので、消したらすぐ確認するのが前提です。復元の考え方はバックアップと復元の4層にまとめています。

2. テンプレートと連携先から先に参照を外す

消えた項目をテンプレートが読んでも、エラーにならず、空欄が表示されるだけなので、誰も気付かないまま公開ページの一部が抜け落ちます。

逆に、止まるのは書き込む側です。移行スクリプトやAI連携が消えた項目へ値を送ると、unknown field というエラーで保存ごと失敗します。テンプレートと連携先から参照を外してデプロイし、それから消す。この順番を守ります。

3. 消したあとに型定義を作り直す

テンプレートの型チェックは、手元の型定義ファイルを見ています。消した項目が型に残っていると、参照の消し忘れに気付けません。本番の定義から型を作り直します。

# 本番の項目定義から TypeScript の型を作り直す
npx emdash types --url https://example.com

seedファイルを本番に追いつかせる

本番で項目を変えたら、seedファイルも同じ形に直しておきます。新しい環境を作ったときに、古い項目のまま立ち上がるのを防ぐためです。

公式の手順は、D1を wrangler d1 export で書き出し、ローカルのSQLiteに入れてから emdash export-seed を実行する流れです。ただ、このサイトのように全文検索を使うD1は書き出しができません。Cloudflareの公式ドキュメントに、仮想テーブル(全文検索の索引)を含むデータベースはexport非対応と書かれています。

そこで私は、本番の項目定義をAPIで取ってseedファイルと1項目ずつ突き合わせています。今日の時点での結果はこうでした。

## blog_posts  本番 6 / seed 6
## projects    本番 13 / seed 13
## pages       本番 14 / seed 14
→ 3コレクション33項目、差分なし

よくある質問

項目の並び順を変えるだけなら安全?

安全です。並び替えは、項目定義の表示順の数字を書き換えるだけで、記事のテーブルには触りません。管理画面の入力欄の順番が変わるだけです。

表示名(ラベル)を変えるとサイトは壊れる?

壊れません。テンプレートが読んでいるのはスラッグで、ラベルは管理画面に出る名前です。クライアントが分かりやすい名前に変えるのは、むしろおすすめです。

クライアントに項目を足してもらっても大丈夫?

おすすめしません。項目の変更は本番にその場で効き、削除は戻せません。項目を触れるのは管理者(Admin)だけなので、クライアントには編集者(Editor)までを渡し、項目の変更は制作側が依頼を受けて行う形にしておくのが安全です。役割の決め方は管理画面をどこまで渡すかにまとめています。

まとめ

項目を1つ足すだけに見える依頼でも、必須にするのか、名前を変えるのか、消すのかで段取りが変わります。作業の前に、次の項目を確かめてください。

最初の項目設計の考え方はフィールド設計の記事にまとめています。

ヘッドレスCMSで作ったサイトの納品後の改修や、運用中の項目追加・整理をお手伝いしています。お問い合わせからお気軽にご相談ください。

本記事は2026年10月時点の情報です(EmDash 0.32.0で確認)。