Grandream
Cloudflare Workers でデモを量産する仕組み|LINEミニアプリの提案を「触れるURL」で通す
はじめに:提案書より、その場で開くURLのほうが速い
LINEミニアプリの相談を受けたとき、こちらが何を作れるかを伝える手段は大きく2つあります。提案書で説明するか、実際に動くものを触ってもらうかです。
私たちは後者に寄せています。会話の途中でURLを送り、相手のスマホでそのまま開いてもらう。これが一番速い。ただしこれを成立させるには、デモを「思いついたときに出せる」状態にしておく必要があります。案件ごとにサーバーを立て、ドメインを取り、SSLを設定して……とやっていると、デモは提案に間に合いません。
この記事では、私たちが実際にデモを量産するために使っている Cloudflare Workers の構成を、wrangler.toml レベルまで公開します。あわせて、すべてのデモを Workers に載せているわけではない、という使い分けの判断も書きます。
1. デモを2種類に分ける
まず前提として、私たちはデモを性質で2つに分けています。
モックデモ:静的HTMLで十分なもの
会員証、モバイルオーダー、順番待ち、スタンプラリー、ビンゴ——このあたりは「画面遷移と操作感」が伝われば目的を達成します。データはダミーで構いません。
こうしたデモはビルド済みの静的HTMLとして本体サイトから配信しています。専用のバックエンドを持たないぶん、デモを増やしても運用の負担が増えにくいのが利点です。デモギャラリーに並んでいるものの大半はこの形式です。
実働デモ:本当に処理が走るもの
一方で、モックでは価値が伝わらないものがあります。たとえば書類をアップロードしてAIが読み取るOCR。ここでダミーの読み取り結果を返しても、相手が知りたいこと(自社の書類が本当に読めるのか)には答えられません。
こちらは実際にAPIを叩き、状態を保存し、レート制限をかける必要があります。この「実働デモ」の置き場所が Cloudflare Workers です。
判断基準はシンプルで、相手が自分のデータを入れたくなるデモかどうか。入れたくなるなら Workers、画面を見せるだけなら静的で十分です。
2. なぜ Cloudflare Workers なのか
フロントとAPIを1つの Worker に同居させられる
Workers Static Assets を使うと、静的ファイルの配信とサーバーサイド処理を1つのプロジェクトに収められます。フロントを別ホスティング、APIを別サーバー、という分割が要りません。
name = "grandream-hp-ocr-demo"
main = "src/index.ts"
compatibility_date = "2026-07-10"
[assets]
directory = "./public/"
binding = "ASSETS"
# 全リクエストを Worker 経由にする
run_worker_first = trueデモ1件がこの十数行から始まります。リポジトリを1つ作り、public/ にフロント、src/index.ts にAPI、wrangler deploy で公開。この短さが量産の前提になっています。
run_worker_first = true が効く理由
この1行が地味に重要です。デフォルトでは静的ファイルへのリクエストは Worker を通らず直接返されます。それだと静的ファイルにだけ認証やヘッダーを掛け忘れることになります。
run_worker_first = true にすると全リクエストが Worker を通ります。認証や noindex ヘッダーそのものは Worker のコード側で実装する必要がありますが、一度書いておけばHTMLだろうが画像だろうが例外なく適用されます。「静的ファイルだけ素通しだった」という抜けを構造的に潰せるのが、この設定の価値です。
独自ドメインなしで即公開できる
<worker名>.<サブドメイン>.workers.dev がそのまま公開URLになります。ドメイン取得もDNS設定もSSL証明書の手配も不要で、デプロイした瞬間にHTTPSのURLが手に入る。提案の直前に「これ、触れますか」と言われて出せるのはこの性質のおかげです。
3. 実際の構成:状態・制限・秘密情報
状態は KV に置く
いまのところ、デモに必要な永続化は Workers KV で足りています。OCRデモではIP単位の1日あたり利用回数を、問診票デモでは送信された問診内容を KV に保存しています。
[[kv_namespaces]]
binding = "SCAN_DAILY"
id = "..."いずれも「キーを引いて1件読む・書く」だけの用途で、リレーショナルDBを立てるほどの構造がありません。KV で足りるうちは KV で済ませる、という割り切りです。逆に検索や集計が要るデモになれば、この判断はやり直すことになります。
レート制限は binding で宣言する
公開デモで一番怖いのは、AIのAPIを叩く口が野ざらしになることです。Workers の Rate Limiting binding を使うと、制限値を wrangler.toml 側に宣言として置けます。
[[ratelimits]]
name = "SCAN_LIMITER"
namespace_id = "1001"
[ratelimits.simple]
limit = 6
period = 60宣言しただけでは効きません。Worker のコード側で limit() を呼び、結果を見て弾きます。
const { success } = await env.SCAN_LIMITER.limit({ key: ip })
if (!success) return json({ error: 'rate_limited' }, 429)制限は「同じ key に対して、Cloudflare の各ロケーション内で60秒あたり6回まで」という効き方をします。全世界で合計6回ではない点は、閾値を決めるときに押さえておく必要があります。
加えて Cloudflare Turnstile をフォームに入れ、自動化されたアクセスを弾いています。レート制限もBot対策も同じ Cloudflare 上で扱えるため、設定箇所が wrangler.toml とシークレット管理に集約されます。
秘密情報は wrangler secret put
APIキーやパスワードは wrangler.toml に書かず、すべて wrangler secret put で登録します。wrangler.toml にはコメントで「何を登録する必要があるか」だけを残しておく。これをやっておくと、別の人がリポジトリを引き継いだときに必要なシークレットが一目で分かります。
# Secrets — 実行前に `wrangler secret put <NAME>` で登録する:
# ANTHROPIC_API_KEY … AI 呼び出し用
# TURNSTILE_SECRET_KEY … Cloudflare Turnstile のシークレットキー
# BASIC_AUTH_USER … 公開前の閲覧制限用
# BASIC_AUTH_PASS … 両方未設定なら認証は無効(素通し)4. 公開範囲をどう絞るか — デモごとに違う
デモは外に出すものなので、公開範囲の設計が要ります。ただしここは「全部に同じ蓋をする」ではなく、デモの性質ごとに変えています。
noindexヘッダーは Workers 上の実働デモに常時付与 — デモが検索結果に載って本体サイトのSEOを荒らすのを防ぐ。ここは条件を付けず、常に付ける- Basic 認証は必要なときだけ — 提案先だけに見せたい期間はサイト全体を閉じる。誰でも触ってよい公開デモでは外す
- 画面単位のパスコード — 問診票デモなら
STAFF_PASSCODEを入れることで、施術者ビューだけを保護できる。一般の閲覧者に見せない画面がある場合の選択肢
たとえば公開デモとして常時開けておきたいものは noindex のみ、提案先限定で見せている段階のものは Basic 認証も足す、という運用です。wrangler.toml にはコメントで「どのシークレットを入れると何が有効になるか」を書き残し、掛け忘れではなく意図的な選択であることが後から分かるようにしています。
設定漏れは公開する側ではなく閉じる側に倒す。 社内向けの経営ボードを Worker で公開したときは、閲覧用の合言葉が未設定なら中身を返さない実装にしました。KPIは社外秘なので、設定漏れが「うっかり全公開」ではなく「誰も見られない」に倒れる形にしてあります。
5. LINEミニアプリのデモに当てはめる
LINEミニアプリは LIFF 上で動くWebアプリなので、この構成とそのまま噛み合います。
- フロント(LIFF側) —
public/に置いて Workers Static Assets で配信 - バックエンド — 同じ Worker の
src/index.tsに実装 - 問診票の提出データのような単純な状態 — KV
- 公開範囲の制御 —
noindexを常時付与し、必要に応じて Basic 認証や画面単位のパスコードを足す
実際に稼働している例が、整体・整骨院・鍼灸院向けに作った問診票ミニアプリです。来店前に患者さんがLINEから問診票を入力し、施術者側の画面で来店前に内容を確認できる。この一連の流れが Worker 1本の中で完結しています。フロントは vanilla JS のハッシュルーターで4画面(LINE風チャット・入力フォーム・送信完了・施術者ビュー)を切り替え、送信内容は KV に保存する。それだけの構成です。
そのほかの会員証・モバイルオーダー・スタンプラリーなどは、先ほど書いたとおりモックとして静的配信しています。デモギャラリーから一覧で触れます。
6. まとめ
デモを量産できるかどうかは、技術力よりも「1件あたりの立ち上げコスト」で決まります。Cloudflare Workers を選んだ理由をまとめると次の3点です。
論点 | Workers での解 |
|---|---|
立ち上げの速さ |
|
フロントとAPIの分割 | Static Assets で1プロジェクトに同居。 |
公開デモの安全性 | Rate Limiting binding・Turnstile・Basic 認証が同一プラットフォーム上に揃う |
そして、すべてを Workers に載せる必要はありません。画面を見せるだけのモックは静的配信、相手が自分のデータを入れるデモだけ Workers。この線引きが、運用するデモの本数を増やしても壊れない理由になっています。
LINEミニアプリの導入を検討していて「まず動くものを見たい」という段階であれば、LINEミニアプリ開発のページからデモをまとめて触れます。同じ Cloudflare Workers で社内の経営KPIダッシュボードを内製した話はこちらの記事にまとめています。
関連記事
Grandream
株式会社グランドリーム
AI・システム開発のプロフェッショナルチームです。AIエージェント・業務自動化・Webシステム開発などを手がけています。




