予約投稿が公開されない|ヘッドレスCMSとCloudflare Workersで「時計」を用意する
「公開日を過ぎたのにサイトマップに載らない」。予約投稿が効かない原因は管理画面ではなくインフラ側にありました。表示とサイトマップの判定のズレ、CloudflareでCron Triggerが要る理由、引き渡し前に見る3点を実装者目線で整理します。

公開日が来た記事が、ブラウザでは普通に開ける。なのにサイトマップに載っていない。うちのブログで実際に起きたことです。記事を並べて公開予約を入れたのに、その時刻を過ぎてもCMS側のステータスは「予約」のまま昇格していませんでした。ページは見えるので、しばらく気づかない。
ヘッドレスCMSやサーバーレス構成でクライアントに「予約投稿できます」と伝える前に、確かめておくことがひとつあります。時計を見る役がいるかどうか。
症状は「ページは開けるのに、サイトマップに載らない」
厄介なのはここです。EmDashの実装を追うと、ふたつの判定が食い違っていました。
- 記事ページや一覧の表示は、ステータスが
publishedのもの、またはscheduledで予約時刻を過ぎたものを出す - サイトマップに収録されるのは、ステータスが
publishedのものだけ
予約時刻を過ぎた記事は、人の目には公開済みとして映るのにサイトマップには現れない。目視のチェックでは絶対に見つからないズレです。うちは公開本数とサイトマップの件数が合わないことで気づきました。

検索エンジンにとっては「まだ存在しない記事」に近い扱いになります。サイトマップまわりの考え方は構造化データとOGPでSEO・AIOを強くするにも書きました。
原因は、誰も時計を見ていないこと
サーバーが常駐している構成なら、CMSのプロセス自身が時刻を見て予約記事を公開へ昇格できます。WordPressの予約投稿も、サイトへのアクセスをきっかけに時刻を確認する仕組みです。アクセスの少ないサイトで公開が遅れる話を聞いたことがあるなら、それがこの仕組みの副作用。
Cloudflare Workersは前提が違います。リクエストが来たときだけ起きて、レスポンスを返したら終わる。誰も見ていない深夜に「そろそろ9時だ」と気づく主体がいません。
EmDashのCloudflareデプロイ手順にも、予約公開・プラグインの定期処理・システムのお掃除はCron Triggerから回すと明記されています。トリガーが無ければ予約公開は動きません。
さらに紛らわしいのが、ローカルの astro dev はプロセス内のスケジューラで動くという点。開発中はきちんと予約公開される。本番に出して初めて壊れる種類の不具合で、これが発見を遅らせました。
直すのに要るのは2か所
やること自体は多くありません。Workerのエントリを scheduled() を持つものに差し替え、cronを宣言するだけ。
// src/worker.ts
export { default, PluginBridge } from "@emdash-cms/cloudflare/worker";// wrangler.jsonc
{
"main": "src/worker.ts",
"triggers": { "crons": ["*/5 * * * *"] }
}つまずきやすい点を挙げておきます。
- アダプタ既定のエントリには
scheduled()がない。EmDash側のWorkerをエントリに据える必要がある PluginBridge(Durable Object)もエントリから再エクスポートする- 粒度は用途しだい。記事の公開に秒単位の正確さは要らないので、うちは5分おきにした。毎分回せばデータベースへの読み書きもその回数だけ発生する
- このハンドラは、公開した項目のエッジキャッシュ無効化も担う。cronを足すまでは、その後始末も走っていなかったことになる

バージョンによって推奨される構成が変わる点にも注意を。うちが使っている0.32系は上の1本で足りますが、より新しいドキュメントでは通常処理とメディア使用状況の2レーンに分ける手順が案内されています。入れているバージョンのドキュメントを見るのが確実です。Cloudflareへ載せる手順そのものはEmDashをCloudflareにデプロイするにまとめてあります。
引き渡す前に見ておく3つ
管理画面をクライアントに渡すなら、「予約投稿できます」と言う前にこの3つを確認しておくと安全です。
- 公開日を過ぎた予約が一覧に残っていないか
- 公開記事の本数と
/sitemap.xmlの件数が一致するか - Workersのログに、定期処理が走った記録が出ているか
配線したあと、一度だけ数を突き合わせました。公開済みが56本、/sitemap-blog_posts.xml に並ぶURLも56件。ここが合っていれば、予約は詰まっていない。合わないときは、公開日を過ぎた予約が残っていないかを先に見ます。

3つめが特に効きます。予約公開は「動いていないことに気づけない」タイプの機能で、記事を1本入れるまで誰も試さない。デプロイ直後にログを一度見ておくだけで、半年後の「なぜインデックスされないのか」を防げます。サーバーを持たない構成で何が消えて何が残るかはCloudflare前提でサーバー保守を抱えないに整理しました。
予約公開そのものは便利な機能です。ただ、それを支えるのは管理画面の中ではなくインフラ側の設定でした。ヘッドレスCMSやCloudflareでの実装、既存サイトの改修でお困りのことがあれば、お問い合わせからお気軽にご相談ください。
本記事は2026年9月時点の情報です。