✅売り子が交代したときにデータを引き継げる機能
利用シナリオ
ユーザーがトップページにアクセスする
ユーザーがアイテムを入力する。初回のアイテム追加時にunlisted URLにURLが切り替わる
ユーザーはアイテムを入力し終え、右上のシェアボタンを押し、LINEやdiscordで売り子にURLを共有する
イベントが始まり、ユーザーは頒布数を記録する
ひと段落してユーザーは休憩に入り、売り子が頒布の記録を引き継ぐ
ユーザーはイベントを見ている途中に頒布数が気になってunlisted URLを閲覧する。売り子が記録したデータがリアルタイムにグラフに反映され、頒布の状況がわかる
ユーザーは家に帰るがCSVエクスポートを忘れる
3日後、データのエクスポートをし忘れたことを思い出したユーザーが慌ててアクセスすると、期限が3日伸びる。ユーザーは即座にCSVデータをエクスポートする。
ユーザーはページを離れる。3日後にデータは自動的に削除される。
仕様
トップページにアクセスし、最初の本を追加すると、URLのpathが予測不可能ユニークな十分長いランダム文字列になる
パスがslugのURLをunlisted URLという
unlisted URLに対応したデータがデータベースに永続化される
unlisted URLにアクセスすると、対応したデータにアクセスできる
複数人が同じページを見ていたら、他人の変更はリアルタイムに反映される
WebSocket 全接続者のリストを保持
受信メッセージを全員にブロードキャスト
定期的にD1へデータ保存
状態を保持し続ける(他のリクエスト間でも)
code:zsh
ユーザーB ─┤ → 同じ DO (slug="abc123") に集約 → 状態共有 unlisted URLのデータは、最終アクセスから3日で削除する
削除はCron Triggerでバッチを実行する
一番上のバーの下に、細いバーとして消える時刻までのメッセージを表示する。背景は警告を表す薄い黄色とする
「このページはリンクを共有した人は誰でも見ることができます。データは YYYY年MM月DD日 hh:mm:ddに削除されます」
削除されたunlisted URLにらアクセスすると、トップページに飛ばされる消える時刻までのメッセージ同様の形式で、「データは有効期限が切れたため削除されました」と表示する。
データの永続化
Cloudlfrare D1にテーブルを作成する
code:zsh
slug PRIMARY KEY
data JSON
last_access TIMESTAMP
created_at TIMESTAMP
シェアボタンの設置
unlistedページにのみ、上部のHAMPのロゴが入っているバーの右端に、シェアボタンを設置する。
シェアボタンはfont awesomeの<i class="fa-solid fa-share"></i>とする
シェアボタンをおすと、unlisted URLがクリップボードにコピーできる
ブルートフォース対策
検索エンジンを拒否
X-Robots-Tag: noindex と robots.txt でクロール拒否
WAF ルール: /(A-Za-z0-9){22} への 404 をカウントし、一定回数で IP/Bot を自動ブロック
手動削除
最下部に手動の削除ボタンを追加ボタンを押すとcronをまたずデータを削除できる
o3.iconリスク残り香
内部リーク:URL を第三者がうっかりブログ・SNS・リファラに流す方がブルートフォースより桁違いに現実的。
手動削除追加で対応基素.icon
乱数器の事故:VM 上の不良 RNG や Seed 共有バグで出現範囲が偏ると理論安全性が崩れる。
統計的スクリーピング:長さやパターンが固定だと、機械学習で「存在しないパス」を高速に除外する研究例もある。
404 と 301 の応答時間差を埋める対策が有効。
この辺りの高度な攻撃の対応はやらない基素.icon
実装
おおむね完成
https://gyazo.com/0138c412d5dc4ecc32bae29f4d093dda
2025-08-15
$ npm run build, typecheck, lintの全てを通るようにして
cloudflareのMCPを入れたのでビルドの失敗をclaude codeが実際に確認することができるようになった。いちいちコピペしなくて済むようになった。
やった結果をフィードバックできない自動化は微妙。この点でnpmなどのコマンドを実行できないLLMは片手おちだ。
Claude Codeとのガチの開発体験は、異常に素早いフィードバックループによって人間だけではあり得ない高速なソフトウェア開発ができている。しかしハマっているところはハマるのでその時の対処がコツかも 典型例:失敗した実装Aと失敗した実装Bを繰り返すような挙動をしたら、そのセッションではうまくいかないとして最初からやり直、別の切り口を検討するべき
TypeScriptプロジェクトにおけるProp-Types問題の解決
問題の概要
npm run build, npm run typecheck, npm run lint でエラーが発生
React PropTypesの検証エラーが大量発生
TypeScript型エラーも存在
根本的な問題
TypeScriptプロジェクトでReact PropTypesルールが有効になっていた
code:ts
// 問題: TypeScriptで型定義済みなのにPropTypesエラー
interface BookItemProps {
book: Book; // ← TypeScriptで厳密に型定義
}
// でもESLintが「PropTypesがない」とエラー
解決方針
PropTypesを完全に無効化(TypeScriptがより優秀な型チェックを提供するため)
具体的な変更
1. ESLint設定の修正 (eslint.config.js)
code:eslint.config.js
rules: {
...reactPlugin.configs.recommended.rules,
...reactHooksPlugin.configs.recommended.rules,
...jsxA11yPlugin.configs.recommended.rules,
// TypeScript使用時はprop-typesは不要
"react/prop-types": "off",
},
2. TypeScript型エラー修正 (workers/app.ts)
code:app.ts
// eslint-disable-next-line @typescript-eslint/no-explicit-any
import("../build/server/index.js" as any).then(
なぜPropTypesが不要か
table:_
PropTypes TypeScript
実行時チェック コンパイル時チェック
曖昧な型定義 厳密な型定義
パフォーマンス負荷あり 負荷なし
JavaScript時代の技術 現代的アプローチ
Junie.iconのエージェントはバグっていて全く動かないので役に立たない
D1を作る
$ npx wrangler d1 create hampu-db
認証エラー(code: 10000)が継続して発生。作成できず
とりあえずwebUIで手動作成
ローカル側
$ wrangler d1 execute hampu-db --local --file=migrations/schema.sql
remote側
認証エラー(code: 10000)が継続して発生。作成できず
logout/loginしても治らないので訳がわからない
ダッシュボードのconsoleからsqlを手打ちした(めんどくさすぎる!!!)
定期削除
workers/apps.tsのscheduledメソッドがcronで実行される
デプロイ
code:zsh
04:01:12.218
DOのbindingsが出ていない
code:成功するとこうなる
Binding Resource
- env.HAMPU_DO (HampuDurableObject) Durable Object
- env.DB (hampu-db) D1 Database
ビルドしていなかっただけだった。再ビルドしたら出た
Claude Sonnet 4.icon
"In order to use Durable Objects with a free plan, you must create a namespace using a new_sqlite_classes migration."
今度はbindingsが表示されました!しかし、フリープランでDurable Objectを使うエラーが出ています。
wrangler.jsonc の migrations セクションを修正してください:
code:jsonc
67 "migrations": [
68 {
69 "tag": "v1",
70 - "new_classes": [
70 + "new_sqlite_classes": [
71 "HampuDurableObject"
72 ]
73 }
new_classesをnew_sqlite_classesに変更しました。フリープランではSQLiteベースのDurable Objectを使う必要があります。
再ビルドしてデプロイしてください:
npm run build
wrangler deploy
TODO
テストが落ちる
WAF対応
グラフが更新されていない
ボタンのデグレ
✅DBはlocalの設定になっているからprodの設定も追加して環境によって呼び替えたい。local環境ではlocalを使い
Claude Sonnet 4.icon
wrangler.jsonc に書かれた database_id はremote(本番)環境のものだけです。
local環境では:
wrangler dev --local 実行時に .wrangler/state/v3/d1 に一時的なローカルDBが自動作成される
database_name を使ってローカルDBにマッピングされる
database_id は無視される
つまり1つの設定ファイルで:
local: database_name でローカルDB参照
remote: database_id でCloudflare D1参照
両方に対応できる仕組みです。
✅(デザイン)警告メッセージが大きすぎるので、小さくしたい
✅(デザイン)ページを削除ボタンは最下部に配置(あまり使われない想定)
✅3日後が日本時間じゃない
UTCをJST扱いで入れていたので9時間ずれていた
✅共有ボタンをfont awesomeにする
https://gyazo.com/f40e60bc84eeb752d65a5bd9c1703856
✅個別ページの表記にslugの名前が大きく出るのがデザイン的に美しくないので、githubのhash表示のようにtipで冒頭のみ表示して欲しい
https://gyazo.com/0cba9a13617e4ca2689b306d39808991
✅app.tsのslug払出しのUintの実装をnanoidに置き換えたい
✅アプリで作成していない、存在しないURLにアクセスされたらトップページにリダイレクトしたい