
言語 🇯🇵 日本語
Val Town インストール
Val Town アプリにライブコメントを追加
Val Town は Deno 上で TypeScript を実行するため、val は実際のサーバーです。これにより FastComments に適しています:ウィジェットはページ上の script タグで、Secure SSO や webhook の検証など、シークレットが必要な処理は同じ val 内でサーバーサイドとして実行できます。
このガイドでは、HTTP val にコメントウィジェットを追加し、インデックスページにコメント数を表示し、既に持っている Val Town アカウントでユーザーをサインインさせ、コメント webhook を受信する方法を説明します。
試すためにアカウントは必要ありません。例では tenantId: "demo" を使用した共有サンドボックスを利用し、ステップ 2 で自分のものに切り替える方法を説明します。
ステップ 1: ウィジェットを追加 
ウィジェットは script タグとコンテナ要素で構成されているため、val がすでにレンダリングしている場所にそのまま埋め込まれます。この例では Hono JSX を使用していますが、これは Val Town の HTTP テンプレートで使用されているものです。
Run 
配信前に urlId を選択
urlId はコメントが属するスレッドを決定します。設定しない場合、現在のページ URL のクリーンアップされたバージョンがデフォルトとなります。これは Val Town で変化する要素そのものです。val はサブドメインを取得するまで長い *.web.val.run ホスト名を持ち、ブランチはそれぞれ独自の URL を持ち、ページの名前を変更するとパスが変わります。各バリエーションは静かに別々の空スレッドとなり、結果として「コメントが消えた」と感じます。
上記のように、投稿スラッグやデータベース ID など、あなたが管理できる安定した値に設定してください。また url も渡すことで、通知メールやモデレーションツールが実際のページへリンクできるようになります。
JavaScript なしでコメントを保持する
Run 
パラメータは URL エンコードしてください。サーバーサイド版は匿名コメントとログインコメント、SSO、そして入れ子返信をサポートしています。
ステップ 2: 自分のアカウントを使用 
tenantId: "demo" は共有のパブリックサンドボックスです。サインアップ不要で動作するため、例で使用されていますが、FastComments を試す他のすべてのユーザーは同じスレッドに書き込み、誰でもそれらをモデレートできます。重要なものを公開する前に切り替えてください。
テナント ID は API シークレットページ にあります。
テナント ID は公開情報で、ブラウザコードに含めるべきものです。API シークレットはそうではなく、このページの何もそれを必要としません。
環境変数から読み取る
Val Town の val は無料プランで公開されているため、ソースは全世界から読み取れます。機密情報は環境変数に保存し、Deno.env.get で読み取ります。
Run 
これは Val Town で通常より重要です。理由は二つ目に、val をリミックスすると環境変数のキーはコピーされますが、値はコピーされません。 環境変数に保存されたシークレットは、あなたの val が他人のアカウントに移行しても引き継がれません。ファイルに書かれたシークレットは引き継がれます。
"demo" にフォールバックすることで、独自のテナントを設定する前にリミックスした人でも val が動作し続けます。
EU アカウント
アカウント、そのデータ、キーはすべて同一リージョンに存在します。もし eu.fastcomments.com で作成した場合、すべてのウィジェット設定にも region: "eu" が必要で、スクリプトは cdn-eu.fastcomments.com からロードされます。そうでなければ、両方ともそのままにしてください。
インデックスページのコメント数 
インデックスページでは、行ごとにコメントカウントウィジェットを1つずつレンダリングしないでください。これは投稿ごとに1リクエストになります。ページ全体で1回のリクエストで済む一括カウントを使用してください。
urlId(スレッドが使用する)で各行にマークし、まとめてウィジェットを1回だけロードします:
Run 
このスクリプトはページ上のすべての .fast-comments-count 要素を検出し、そのカウントを埋め込みます。
data-fast-comments-url-id は、投稿のコメントウィジェットが使用する urlId と一致する必要があります。ウィジェットがスラッグを使用する場合、マーカーもスラッグを使用します。不一致の場合、コメントがあるスレッドでも0が表示されます。
スクリプトは window.FastCommentsBulkCountConfig をポーリングするため、設定をスクリプトタグの前に置くか後に置くかは関係ありません。
std/oauth による安全な SSO 
If your val already knows who the visitor is, Secure SSO hands that identity to the widget so they never see a second login. There are no endpoints to build and nothing to call at runtime: you compute three values server-side and pass them in the widget config.
Val Town ships zero-config login with std/oauth, so the visitor can sign in with the Val Town account they already have. Swap that for whatever your app uses; the FastComments half does not change.
サーバー側でペイロードを構築する
The API secret signs the payload and must never reach browser code. Install the SDK from npm, which works on Val Town's Deno runtime as-is:
Run 
getPayload() returns { userDataJSONBase64, verificationHash, timestamp }. Those three values are all that reach the browser. The secret signs them and is then dropped, so nothing in the page lets a reader forge a different user.
ウィジェットに渡す
Run 
oauthMiddleware adds GET /auth/login, GET /auth/callback and POST /auth/logout for you. Note that logout is a POST, while the widget navigates to logoutURL with a GET, so point logoutURL at a small route of your own that submits the POST.
When the visitor is logged out, pass sso with only a loginURL. The widget then shows a login prompt instead of an anonymous comment box.
問題が起きたとき
timestamp is epoch milliseconds, must not be in the future, and must not be more than two days old. Generate it on the server in the same request that computes the hash. Generating it in the browser is the classic failure: the value differs from the one that was hashed and every comment is rejected.
Never set isAdmin or isModerator from the identity provider. Signing in with a Val Town account says nothing about who should moderate your site.
See the SSO guide for the full field list, group-gated threads, and badges.
Webhook の受信 
A val は自然な Webhook 受信者です。安定した URL を持ち、署名を検証でき、SQLite と BLOB ストレージが組み込まれています。
FastComments は ${timestamp}.${body} にアカウントの API シークレットで署名し、2 つのヘッダーを送信します。
Run 
このメソッドはイベントを伝えます。作成または更新されたコメントには PUT、削除されたコメントには DELETE を使用します。
Run 
問題となる2つの点
生バイトを検証する。 JSON を解析して再シリアライズするとキーの順序や空白が変わり、ハッシュが一致せず、明確な原因なしにすべての配信が失敗します。これが Webhook 受信者が「うまく動かない」一般的な理由です。
一定時間で比較する。 署名に対して単純な === を使用すると、何バイト一致したかが漏洩し、1 バイトずつ偽造するのに十分です。
イベントの処理
迅速に応答してください。FastComments は 2xx 以外のステータスで再試行し、失敗が続くエンドポイントは最終的に自動で無効化されます。そのため、インラインで処理せずにレスポンスを返した後に実際の作業を行ってください。
コメント ID に対して冪等に動作させてください。再試行時には新しいタイムスタンプで再署名され、編集や削除時に同じコメント ID が再度届くため、重複排除できる安定した情報はありません。
例 Vals 
Four public vals you can remix, each covering one piece of this guide.
Blog with comments (live) は、各投稿の下にスレッドがあり、インデックスでコメント数を一括表示するMarkdownブログです。リミックスした瞬間に動作し、1つの環境変数で自分のアカウントを指すようになります。
SSO demo (live) は、訪問者をVal Townアカウントでサインインさせ、そのアイデンティティをウィジェットに渡すので、二度目のログインは不要です。
Webhook receiver (live) は、各配信でHMAC署名を検証し、イベントをSQLiteに保存します。テストペイロードに署名して自身に配信するボタンがあり、実際のWebhookを設定する前に検証が成功する様子を確認できます。
Agent skills (live) は、ウィジェット、SSO、REST API、モデレーション、Disqusからの移行をカバーするFastCommentsエージェントスキルのライブラリです。リミックスすると、Val TownのエージェントであるTownieが skills/ から自動的にスキルを取得するため、チャットにドキュメントを貼り付けなくてもエージェントがコメント機能を設定できるようになります。
同じスキルは、npx skills add fastcomments/skills を使って他の場所にもインストールできます。
ドメインエラー 
Once you switch off the demo tenant, the widget may refuse to load with an authorization error. This is because FastComments doesn't know it's supposed to allow your account to be used on that domain.
Go here to add your site to your account.
Val Town is worth a second look here, because a val can be reachable at more than one hostname:
- Every HTTP val has a long default endpoint,
<org>--<id>.web.val.run. - Claiming a custom subdomain adds
<name>.val.run. - A カスタムドメイン adds a third.
- Branches get their own URLs.
Add whichever hostnames you actually serve the widget from. If you claim a subdomain after setting things up, add that too, or the widget works on the old URL and fails on the new one.