Share HTML について
Share HTMLは、単体HTMLファイルをサンドボックス化されたプレビューとして共有するCloudflareホストのサービスです。ページURLをすぐに用意したい人やエージェント向けに、非公開リンクまたはアクセスキー付きリンクとHTMLリスクスキャンを提供します。
主な機能
- 01単一HTMLファイルのアップロード
- 02非公開または保護付きリンクの作成
- 03サンドボックス内でのHTMLプレビュー
- 04不審なHTMLパターンのスキャン
- 05アカウントで共有を管理
- 06直接プレビューURLの提供
活用シーン
- 01サイトを構築せずにプロトタイプを共有
- 02モックアップや小規模デモをURLで送信
- 03アクセスキー保護付きプレビューの配布
- 04アカウント経由でアップロードを保持・削除
MCP 対応
リモートMCPサーバーは `describe_share_html`、`get_public_share`、`create_share` を提供します。`create_share` は非公開リンクとプライベートリンクに対応し、ウェブアップロードと同じレート制限およびリスクスキャンを適用します。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://share-html.zhenjiazhou0127.workers.dev/mcpclaude mcp add --transport http lifeodyssey-share-html https://share-html.zhenjiazhou0127.workers.dev/mcp{"mcpServers":{"lifeodyssey-share-html":{"type":"http","url":"https://share-html.zhenjiazhou0127.workers.dev/mcp"}}}Cursor で開く{"servers":{"lifeodyssey-share-html":{"type":"http","url":"https://share-html.zhenjiazhou0127.workers.dev/mcp"}}}VS Code で開く{"mcpServers":{"lifeodyssey-share-html":{"type":"http","url":"https://share-html.zhenjiazhou0127.workers.dev/mcp"}}}{"mcpServers":{"lifeodyssey-share-html":{"serverUrl":"https://share-html.zhenjiazhou0127.workers.dev/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
3このツールにパラメーターはありません。
詳細
HTML を共有する
利用状況調査は /report/0923 で確認できます。2026年9月23日のレポートでは固定されたスナップショットを使用し、集計結果と匿名化されたユースケースのみを公開しています。
ファーストパーティ分析では、ブラウザのレポート、HTTP/MCP のビジネス成果、獲得シグナル、ボットの証拠を分けて記録しています。分析に関する設定、データの制限、保持期間、GA4 の設定については、計測の仕様と運用ガイドを参照してください。ANALYTICS_ENABLED=true を指定してデプロイする前に、分析用マイグレーションを適用してください。サービスが有効な場合、ブラウザ分析はデフォルトで有効になり、分析設定から無効にできます。既存のオプトアウト、DNT/GPC、または読み取りできない設定ストレージがある場合は、データを収集しません。対象となるブラウザイベントには、専用の Share HTML GA4 プロパティを使用します。拡張計測は無効になっており、非公開の共有ページから Google イベントは送信されません。
HTML ファイルを 1 つアップロードし、サンドボックス化されたプレビューを、非公開の公開リンクまたはアクセスキーで保護された非公開リンクとして共有できます。
リンク
- 公開アプリ:https://sharehtml.zhenjia.dev
- GitHub リポジトリ:https://github.com/lifeodyssey/share-html
- Workers のフォールバック:https://share-html.zhenjiazhou0127.workers.dev
プロジェクトドキュメント
- 製品およびシステムの仕様:docs/project/spec.md
- 現在の進捗:docs/project/progress.md
- ロードマップ:docs/project/roadmap.md
機能
Share HTML は、自己完結型の HTML ファイルを共有するための、Cloudflare でホストされる小規模なツールです。サイトを用意せずに URL が必要な場合に、簡易プロトタイプ、モックアップ、レシート、小規模なデモ、一度限りのページを手軽に共有できます。
- 365 日で期限切れになる匿名アップロードフロー。
- 共有ファイルの保存や削除に使用する Supabase のマジックリンク認証。認証メールの送信は Cloudflare Email Service が処理します。
- 後から匿名アップロードをアカウントに紐付けるためのクレームトークンフロー。
- 非公開の公開リンクと、アクセスキーで保護された非公開リンクの公開設定モード。
- 必要に応じて非公開リンクのロックを解除すると、ステータス、リスクスコア、埋め込みプレビューを表示する共有ページ。
- アップロードした HTML を単独で開くための直接プレビュー URL。
- 疑わしい HTML パターンを検出する軽量スキャナー。
- レポート API と管理者向けモデレーションエンドポイント。
URL の種類
Share HTML は、アップロード後に意図的に異なる 2 種類の URL を公開します。
- Share URL は、
/s/:slugにあるラッパーページを開きます。ステータス、安全性に関する情報、報告アクション、埋め込みプレビューが含まれるため、共有するリンクとして最適です。 - Preview URL は、
/v/:slug/にあるサンドボックス化された HTML レンダリングを開きます。プライベートリンクの場合、ロック解除時に作成された有効期間の短いプレビュー Cookie が必要です。 - Claim token は非公開です。匿名でアップロードしたデータを自分のアカウントに移す場合は、サインイン後に共有 ID とともに使用してください。
各アップロードでは、公開範囲も 1 つ選択します。
public_unlistedがデフォルトです。URL を知っている人なら誰でもメタデータを読み取り、プレビューを開けます。共有ルートとプレビュールートには noindex が設定され、sitemap.xmlに追加されることはありませんが、限定公開は認証済みと同じではありません。private_linkは、32 バイトの base64urlaccessKeyを返します。返されるshare.share_urlには、クライアント側の#key=フラグメントにキーが含まれるため、最初の HTTP リクエストでキーがサーバーに送信されることはありません。プライベート URL 全体は秘密として扱ってください。
claimToken と accessKey は、意図的に異なる権限を持ちます。前者はサインイン後に所有権を移転し、後者はプライベートリンクを開くためのもので、所有権は付与しません。
HTTP API
パブリック限定公開の共有を作成します(デフォルト)。
curl -X POST https://sharehtml.zhenjia.dev/api/shares \
-F '[email protected]' \
-F 'title=My page'
プライベートリンクを作成します。
curl -X POST https://sharehtml.zhenjia.dev/api/shares \
-F '[email protected]' \
-F 'visibility=private_link'
どちらの成功レスポンスも同じ形式です。
{
"share": { "id": "...", "slug": "...", "share_url": "...", "preview_url": "..." },
"claimToken": "... or null",
"accessKey": "... or null",
"message": "Uploaded."
}
public_unlisted の場合、accessKey は null です。ブラウザーのラッパーを使わずにプライベートリンクのロックを解除するには、次のようにします。
curl -X POST https://sharehtml.zhenjia.dev/api/shares/SLUG/access \
-H 'content-type: application/json' \
--data '{"accessKey":"PRIVATE_ACCESS_KEY"}'
成功すると { "share": ... } が返され、有効期間の短いホスト限定 HttpOnly グラントが 2 つ設定されます。1 つはプレビュー用に /v/:slug にスコープされ、もう 1 つは正確なロック解除エンドポイントにスコープされます。これにより、ブラウザーがアドレスバーから #key を削除した後も、更新時にメタデータを復元できます。プライベートリンクに対する単純な GET /api/public/shares/:slug は、code: "share_access_required" を伴う 401 を返します。誤ったキーの場合は、code: "invalid_share_access_key" を伴う 403 を返します。キーをクエリパラメーターに移したり、プライベート URL 全体をログ、問題報告、パブリック出力に含めたりしないでください。
認証済みの所有者は、POST /api/shares/:id/access-key を使って、紛失または漏えいしたプライベートキーを置き換えられます。ローテーションでは新しいキーが 1 度だけ返され、以前のキーに対して発行されたメタデータおよびプレビューのグラントは直ちに無効になります。
エージェントからのアクセス
Share HTML は、人間だけでなく AI エージェントからも発見し、利用できるように構築されています。
llms.txt— AI が読み取れるサイトガイドです(リクエストにAccept: text/markdownが含まれる場合は、/からも配信されます)。openapi.json— 両方の公開範囲モードと、非公開のロック解除/Cookie フローを含む、機械可読な HTTP API の説明です。ホームページの HTML にも静的コンテンツと JSON-LD が埋め込まれているため、JavaScript を使わないエージェントもサイトの概要と呼び出し方法を確認できます。- MCP マシンエンドポイント —
https://share-html.zhenjiazhou0127.workers.dev/mcpは、describe_share_html、get_public_share、create_shareを公開します。ブランドサイトと同じ本番 Worker を使用し、マシン間通信に対するゾーンレベルのブラウザーボットポリシーを回避します。このページでは、WebMCP(navigator.modelContext)を介して、同じツールをブラウザー内でも公開します。 /a2a—describe_share_htmlスキルを実装した A2A 1.0 JSON-RPC エンドポイントです。カードには、実行可能なこの A2A 機能のみが意図的に掲載されています。- WebMCP の
create_shareでは、エージェントがpublic_unlistedまたはprivate_linkを選択できます。access_private_shareは、アクセスキーをメタデータと、範囲が限定されたメタデータおよびプレビューの許可情報と交換します。どちらも通常の HTTP API を介して実行されます。 - MCP の
create_shareは、public_unlistedとprivate_linkの両方に対応しています。ウェブアップロードと同じ匿名ユーザー向けレート制限とリスクスキャナーを介して実行されます。迂回経路はなく、非公開の作成時にはキーが一度だけ返されます。 - 検出用ファイル:明示的な AI ボットルールを含む
robots.txt、sitemap.xml、auth.md、および/.well-known/リソース(api-catalog、mcp/server-card.json、webmcp.json、agent-skills、agent-card.json、OAuth/OIDC メタデータ、security.txt)。不明な/.well-known/パスでは、SPA シェルではなく404を返します。
ファーストパーティのホームページと検出ドキュメントでは、検索インデックスへの登録とリアルタイム AI 入力を許可し、レスポンスレベルの Content-Signal によって AI トレーニングをオプトアウトしています。ユーザーが提供する共有メタデータとプレビューには、より厳格な search=no, ai-input=no, ai-train=no, use=immediate を設定し、noindex にして、サイトマップには決して掲載しません。このレスポンスレベルでの切り分けにより、同じホスト上のアップロードコンテンツにファーストパーティの GEO 許可が適用されるのを防ぎます。
獲得ループ
このプロダクトでは、検出用ファイルだけに頼るのではなく、クロール可能なファーストパーティのエントリーページを4つ用意しています。
/html-previewでは、単一ファイルのプレビューの範囲を説明し、アップロードへの CTA を設けています。/private-html-sharingでは、アクセスキーによるプライバシー保護とその制限を説明しています。/examplesでは、アップローダーに事前読み込みできる、自己完結型のファイルを3つ提供しています。/agentsでは、MCP、HTTP、OpenAPI、WebMCP、Skill、A2A の実用的なエントリーポイントを提供しています。
sitemap.xml に登録されているのは、これらのページとホームページのみです。アップロードされた /s/:slug と /v/:slug/ の URL は引き続き noindex で、すべての検出用送信から除外されています。ラッパーページには「HTML を共有」という CTA が表示されます。その source=shared_preview 値は、visibility とともに既存の created イベントのメタデータにのみ保存されるため、新しいトラッキングサービスを追加せずに、プロダクト主導の利用開始を測定できます。
公式 MCP Registry の正規 ID は dev.zhenjia/share-html で、zhenjia.dev の DNS に公開された Ed25519 公開鍵によって認証されます。その記述子は server.json で、ホームページのリンクからエージェントを /agents のライブ統合ガイドに案内します。リモートサーバー自体は本番環境の workers.dev マシンエンドポイント上に置き、ユーザー向けページと正規 URL は sharehtml.zhenjia.dev に維持します。この分離により、ブランドドメインで Free プランの Bot Fight Mode が正規のデータセンター MCP クライアントを拒否するのを防ぎます。
手動の Publish MCP Registry metadata ワークフローでは、ライブマニフェストと MCP ツールリストを検証し、production 環境のシークレット MCP_REGISTRY_PRIVATE_KEY を使ってブランド ID を公開し、Registry の正確な投影を検証してから、レガシー ID io.github.lifeodyssey/share-html を移行メッセージ付きで非推奨としてマークします。Registry のバージョンは現在取り下げられないため、このワークフローは意図的に冪等であり、本番エンドポイントのデプロイと検証後に publish-dev-zhenjia と入力する必要があります。DNS 認証用の秘密鍵を、リポジトリ、Worker の設定、ログ、ワークフローのアーティファクトに決して置かないでください。
このホスト名ではプライベート URL と非公開 URL も配信されるため、IndexNow では Cloudflare Crawler Hints を使わず、明示的なファーストパーティの許可リストを使用します。
npm run growth:indexnow:dry-run
printf '%s' '<8-to-128-character-key>' | npx wrangler secret put INDEXNOW_KEY
INDEXNOW_KEY='<same-key>' npm run growth:indexnow
Worker は、その環境値が設定されている場合に限り、/{INDEXNOW_KEY}.txt を配信します。送信スクリプトは、グローバル IndexNow エンドポイントに接続する前に、/s/、/v/、/api/、およびオリジンの異なる URL を拒否します。
スタック
- アプリシェルと API に Cloudflare Workers Static Assets を使用します。
- アップロードされた HTML オブジェクトに Cloudflare R2 を使用します。
- ブランド認証メールの配信に Cloudflare Email Service を使用します。
- マジックリンクユーザーの認証に Supabase Auth を使用します。
- メタデータ、レポート、イベント、モデレーション状態に Supabase Postgres を使用します。
- フロントエンドに React、Vite、TypeScript を使用します。
ローカルセットアップ
npm install
cp .env.example .dev.vars
npm run build
npm run dev
本番環境へのデプロイ前に、以下の Cloudflare Worker シークレットを設定してください。
printf '%s' '<legacy-anon-key>' | npx wrangler secret put SUPABASE_REST_KEY
printf '%s' '<worker-api-secret>' | npx wrangler secret put WORKER_API_SECRET
printf '%s' '<random-salt>' | npx wrangler secret put IP_HASH_SALT
printf '%s' '<independent-random-32-byte-secret>' | npx wrangler secret put SHARE_ACCESS_PEPPER_V1
printf '%s' '<different-random-32-byte-secret>' | npx wrangler secret put PREVIEW_GRANT_SIGNING_KEY_V1
printf '%s' '<8-to-128-character-key>' | npx wrangler secret put INDEXNOW_KEY
printf '%s' 'v1,whsec_...' | npx wrangler secret put SUPABASE_SEND_EMAIL_HOOK_SECRET
SHARE_ACCESS_PEPPER_V1 は保存されるアクセスキーのハッシュを導出し、PREVIEW_GRANT_SIGNING_KEY_V1 は有効期間の短いメタデータとプレビューの許可情報に署名します。それぞれを個別に生成し、どちらの V1 値もその場で置き換えないでください。導出方式をローテーションする場合は新しいバージョンを追加し、保存されている access_key_version の値を移行してください。許可情報のローテーション時は、署名キーの重複利用期間を設けてください。
公開プレビューでは、別途 PREVIEW_ORIGIN を使用できます。非公開プレビューでは、意図的に APP_ORIGIN を使用します。これは、有効期間の短い認可 Cookie がホスト限定で、/v/{slug} にスコープされるためです。レスポンスの CSP sandbox では allow-same-origin を省略しているため、アップロードされた HTML がアプリのオリジンを継承したり、そのストレージを読み取ったりすることはできません。
R2 バケットを一度だけ作成します。
npx wrangler r2 bucket create share-html-prod
Supabase のすべてのマイグレーションをファイル名順に適用してください。既存のデプロイでは、supabase/migrations/0003_private_share_access.sql を適用し、この変更の Worker コードをデプロイする前に、バージョン管理された両方の非公開共有用シークレットを設定してください。このマイグレーションは既存の公開専用 Worker との後方互換性がありますが、新しい Worker は、すべてのアップロードで visibility、access_key_hash、access_key_version を書き込むため、古いスキーマとは互換性がありません。
0003 を適用する前に、既存の profiles.role = 'admin' の行を正式な管理者許可リストと照合し、想定外の行があればリセットしてください。このマイグレーションは、テーブル全体に対するブラウザーからの従来の UPDATE 権限を閉じ、セルフサービスでのプロフィール編集を display_name に制限します。ただし、すでに保存されている管理者ロールが正当なものかどうかは判定できません。
本番環境のマジックリンクを使用するには、Supabase Auth のサイト URL とリダイレクト許可リストに https://sharehtml.zhenjia.dev を追加してください。
Cloudflare Email Service フックと [email protected] の送信者設定に関する注意事項は、docs/email/auth-email-setup.md にあります。
デプロイ
本番環境は、share-html という名前の Cloudflare Worker として稼働します。デプロイ設定の正式な情報源は wrangler.jsonc です。このファイルでは、Worker のエントリーポイント、静的アセット、カスタムドメイン、R2 バケットのバインディング、公開ランタイム変数を定義しています。
デプロイは GitHub のブランチ保護によって制御され、Cloudflare Workers Builds によって実行されます。
- プルリクエストでは、
npm ci、npm run build、npx wrangler deploy --dry-runを実行します。 mainブランチでは、変更をマージする前にBuildチェックの成功が必須です。- Cloudflare Workers Builds は
mainを監視し、そのブランチをビルドして、マージ後に Worker をデプロイします。
これにより、Cloudflare のデプロイ認証情報を GitHub に置かずに済みます。GitHub Actions に Cloudflare API トークンやデプロイフックのシークレットを設定する必要はありません。
Cloudflare Workers Builds の設定に関する注意事項は、docs/deploy/cloudflare-builds.md にあります。
ローカルマシンから手動でデプロイすることもできます。
npm run deploy
Worker は以下のように設定されています。
- カスタムドメイン:
sharehtml.zhenjia.dev - Worker のフォールバック:
share-html.zhenjiazhou0127.workers.dev - R2 バケット:
share-html-prod
/robots.txt の正式な情報源も Worker です。このホスト名では、Cloudflare のダッシュボードレベルの Managed robots.txt の挿入を無効にしてください。有効にすると、Cloudflare が Worker のレスポンスの前に、2つ目のワイルドカードグループと Content Signals ポリシーを追加します。
セキュリティに関する注意事項
アップロードされた HTML はサニタイズされません。代わりに隔離されます。
- プレビューページは、専用の
/v/:slug/ルートを通じて配信されます。 - 共有ページでは、iframe サンドボックス内にプレビューが埋め込まれます。
- R2 オブジェクトは非公開で、Worker のみが読み取れます。
- プレビューのレスポンスには、制限的なレスポンスヘッダーが適用されます。
- レスポンスレベルの CSP
sandboxではallow-same-originが省略されるため、プレビューをトップレベルのタブで開いた場合も、アップロードされたスクリプトのオリジンは不透明なままです。 - アップロードされたコンテンツを配信する前に、モデレーション状態が確認されます。
- プライベートリンクのメタデータにアクセスするには、アクセスキー、所有者セッション、または有効なメタデータ許可が必要です。プレビューには、別途、短期間かつパススコープ付きの HttpOnly 許可が必要です。
- プライベートアクセスキーは、ブラウザー間で受け渡すために共有 URL のフラグメントに含まれます。フラグメントは HTTP リクエストで送信されませんが、URL 全体を引き続き秘密情報として扱う必要があります。
- Supabase RLS では、サーバー側のメタデータ書き込みに非公開の Worker シークレットヘッダーが必要です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。